Skip to content

Move the server-less subcommands from server to trajecta - #11

Merged
kingfs merged 1 commit into
mainfrom
feat/trajecta-cli-migrate-server-commands
Oct 21, 2026
Merged

kingfs merged 1 commit into
mainfrom
feat/trajecta-cli-migrate-server-commands

Conversation

@kingfs

@kingfs kingfs commented Oct 16, 2026

Copy link
Copy Markdown
Owner

What

server carried eleven command groups that never needed the proxy process. This moves them to the trajecta CLI, so server is only about running the binary.

Stays in server: serve (also the bare server -c config.yaml invocation), version, completion.

Migrated to trajecta: analyze, audit, auth, config, db, doctor, migrate, models, provider, schema, tools.

A command that used to be server db migrate status is now trajecta db migrate status with the same subcommands, flags, exit codes and JSON shape.

How

  • internal/cli now holds the shared CLI contract (exit-code table, JSON envelope, the viper-backed Runtime owning -c/--config and --format, the Execute top-level error path) together with the migrated command bodies, because the command bodies were already written against that contract. cmd/server imports the contract for its own three commands and registers none of the migrated ones; cmd/trajecta binds the same two flags and calls cli.Register.
  • internal/appdb collects the application-database entry points that serve startup and the db/auth commands share — driver normalization, migration mode, MigrateUp/OptimizeIndexes, Open/Initialize and the auth store opener — so the startup path and the commands can no longer drift apart.
  • NormalizeMCPPath/ValidateServe moved to internal/config, the provider-probe target helpers to internal/providerprobe.
  • Behaviour change: trajecta now reports failures through the shared contract. Error envelopes go to stderr (they used to go to stdout, which is what lets trajecta ... --format json > state.json stay parseable) and internal failures exit 8 instead of 1. Commands that emit an ok: false envelope and then return an error still write exactly one JSON object per stream.
  • The tests split with the commands: serve-side tests stay in cmd/server (serve_commands_test.go), the app-db helper tests moved to internal/appdb, and the rest run against the shared runtime in internal/cli.
  • Taskfile.yml runs migrate, migrate:db:up, auth:init-user and auth:create-token through go run ./cmd/trajecta, and task test:e2e covers ./cmd/trajecta.
  • Docs, README.md/README_EN.md, AGENTS.md and CHANGELOG.md describe the split.

Verification

task fmt, golangci-lint run ./... (0 issues), go vet ./..., go test -short ./... and task test:e2e are green.

End-to-end against SQLite with both binaries built from this branch:

  • server --help lists only completion, serve, version; server db … exits 3 with unknown command "db" for "server".
  • trajecta db migrate status/up --check-db, db migrate optimize-indexes, config inspect, doctor, tools status, db secret status/export/rotate, auth init-user, auth create-token, auth migrate status, models codex-config, provider probe, provider probe-report, schema, schema auth create-token, audit query, audit tool-calls, db summary rebuild sessions, analyze scan/reparse/repair-usage/refresh/backfill-exchanges and migrate all succeed against a config the server owns.
  • A real server recorded streaming and non-streaming /v1/chat/completions round trips plus a /v1/responses request through the local Responses runtime, and trajecta audit query --response-id … read back the audit rows serve wrote.
  • Exit codes checked: unknown command and bad --format → 3, db migrate down → 3, failing doctor → 1.

`server` carried eleven command groups that never needed the proxy process.
Move them to the `trajecta` CLI, so `server` is only about running the
binary: `serve` (also the bare invocation), `version` and `completion`.

Migrated to `trajecta`: analyze, audit, auth, config, db, doctor, migrate,
models, provider, schema, tools.

- `internal/cli` now holds the shared CLI contract (exit codes, JSON
  envelope, the viper-backed Runtime owning `-c/--config` and `--format`,
  the `Execute` top-level error path) together with the migrated command
  bodies. `cmd/server` imports the contract for its own three commands and
  registers none of the migrated ones; `cmd/trajecta` binds the same two
  flags and calls `cli.Register`.
- `internal/appdb` collects the application-database entry points serve
  startup and the `db`/`auth` commands share (driver normalization,
  migration mode, MigrateUp/OptimizeIndexes, Open/Initialize, auth store
  opener). `NormalizeMCPPath`/`ValidateServe` moved to `internal/config`
  and the provider-probe target helpers to `internal/providerprobe`.
- `trajecta` now reports failures through the shared contract: error
  envelopes go to stderr and internal failures exit 8. Commands that write
  an `ok: false` envelope and then return an error still emit exactly one
  JSON object per stream.
- Tests split with the commands: serve-side tests stay in `cmd/server`
  (`serve_commands_test.go`), the app-db helper tests moved to
  `internal/appdb`, and the rest run against the shared runtime in
  `internal/cli`.
- Taskfile, docs, README/README_EN and AGENTS describe the split; the
  `test:e2e` package list covers `./cmd/trajecta`.

Verified end to end against SQLite: `trajecta db migrate up/status`,
`config inspect`, `doctor`, `tools status`, `db secret status/export/rotate`,
`auth init-user/create-token`, `models codex-config`, `provider probe`,
`schema`, `audit query`, `analyze scan/reparse/repair-usage/refresh/
backfill-exchanges` and `migrate`, with a real `server` recording streaming
and non-streaming chat completions plus a local-Responses request, and
`trajecta audit query` reading back the rows that serve wrote.
@kingfs
kingfs merged commit 1402a24 into main Oct 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant