CLI Commands Reference
This note provides implementation details for AD-010 and AD-011.
kapi (with bowrain plugin) command tree
Once the kapi-bowrain plugin is installed, every command below runs as
kapi <command>.
kapi
+-- init # Initialize a new .kapi project (recipe + state dir)
| +-- --name, --source, --targets, --server, --project, --anonymous, --email, --preset
+-- config # The one config verb: recipe keys positionally (name, server.url, …)
| +-- get/set/unset/list/path # per-machine app config; bowrain.* routes to bowrain/bowrain.yaml under the user config dir
+-- ls # List tracked files with optional stats
| +-- --stats/-s, --dirty/-d, [paths...]
+-- add # Add file patterns to track
| +-- --format/-f, <pattern> [pattern...]
+-- rm # Stop tracking files (remove mapping or add exclude)
| +-- <pattern> [pattern...]
+-- status # Show sync state (local vs remote)
+-- diff # Show changes between local and remote
+-- pull # Pull from Bowrain Server -> update local files
| +-- --force, --dry-run, --locale (repeatable), --stream, --concepts
+-- push # Push local files -> update Bowrain Server
| +-- --force, --dry-run, --stream, --concepts, [paths...]
+-- serve # Start local dashboard (web UI)
| +-- --port 3000, --no-open
+-- auth # Authentication with Bowrain Server
| +-- login # OAuth device flow login (--server)
| +-- logout # Remove stored token
| +-- status # Show current user, server URL
| +-- claim # Claim anonymous project
| +-- token # Manage API tokens (create, list, delete)
+-- workspace # Manage workspaces (list, create)
+-- stream # Manage content streams (list, create, diff, merge, archive, status)
+-- run FLOW # Execute a flow (inline on recipe, .kapi/flows/, or built-in)
+-- <tool> # Run a tool directly (pseudo-translate, translate, qa, etc.)
+-- flows # List available flows
+-- tools # List available tools
+-- sync # Sync operations (push + translate + pull)
+-- ui # Launch the Bowrain desktop app
+-- terms # Terminology management
| +-- list # List terminology entries
+-- formats # Format listing
| +-- list # List available formats (built-in + plugin)
+-- plugins # Plugin management
| +-- list # List installed plugins
+-- presets # Preset management
| +-- list # List presets
| +-- validate # Validate project preset references
+-- version # Show version info
+-- mcp # Start MCP server for AI agent integration
kapi command tree
kapi
+-- <tool> # Run a tool directly (pseudo-translate, translate, qa, etc.)
+-- run FLOW # Execute a composed multi-tool flow (translate-qa, etc.)
+-- tools # List available tools
+-- flows # List available flows
+-- formats # Format listing
| +-- list # List available formats (built-in + plugin)
+-- plugins # Plugin management
| +-- list # List installed plugins
+-- presets # Preset management
| +-- list # List presets
+-- terms # Terminology management
| +-- list # List terminology entries
+-- version # Show version info
+-- mcp # Start MCP server for AI agent integration
kapi init Workflows
Interactive Mode (default when stdin is a terminal)
- If already signed in: select workspace -> enter project name -> select source locale
- If not signed in: choose from Sign in / Email claim / Anonymous / Local only
- Workspace selector allows choosing existing workspaces or creating new ones
- Source locale uses a BCP-47 selector with type-ahead filtering
Non-interactive Workflow
- Check if
kapi.yamlor.kapi/already exists (error if so) - Write
kapi.yamlrecipe with defaults or provided flags - If
--anonymousor--email: create anonymous project on server, writeserver:block - If
--projectprovided: verify auth and connect to existing project, writeserver:block - If authenticated with no flags: create project in personal workspace, write
server:block - Create
.kapi/flows/directory with example flows - Add
.kapi/to.gitignore
All paths support --json output for CI/CD integration.
kapi pull Algorithm
- Read the recipe (
server.url, content collections) - Verify auth token (keychain
bowrain-auth:<server-url>orBOWRAIN_AUTH_TOKEN) - Call
GET /api/v1/projects/:id/sync/pull?cursor=X&locales=...- Response: changes since cursor, new cursor, has_more
- Paginated: follow has_more until all changes consumed
- Write blocks to local files via FormatRegistry
- If the project is workspace-claimed, snapshot governed terminology: paginate
GET /api/v1/:ws/concepts, fetch each concept's relations viaGET /api/v1/:ws/concepts/:cid/relations, and write both into the project terms store (.kapi/terms.db) throughAddConcept/AddRelation. Record aConceptBaselinein the sync cache so a laterkapi pushcan diff local terminology edits against it. - Run
post-pullhooks (if configured) - Update
.kapi/cache/sync-cache.json
Conflict handling:
- By default, pull fails if local files have uncommitted changes
--forceoverwrites local changes
kapi push Algorithm
- Read the recipe (content collections)
- Run
pre-pushhooks (qa, term-enforce, etc.)- If any hook fails, abort push
- Read local files via FormatRegistry
- Compute block hashes
- Compare with
.kapi/cache/sync-cache.json-> identify changed blocks - Verify auth token (keychain
bowrain-auth:<server-url>orBOWRAIN_AUTH_TOKEN) - Call
POST /api/v1/projects/:id/sync/push- Request body:
{ blocks: [{id, text, name, type, item_name}] } - Response:
{ stored: N, new_cursor: X, push_id: "..." } - Batched at 1000 blocks per request (MaxBlocksPerRequest)
- Request body:
- Update
.kapi/cache/sync-cache.json
REST API Routes
Public Routes
GET /api/v1/health
GET /api/v1/config # Server configuration
GET /api/v1/info # Server information
GET /api/v1/formats # List supported formats
GET /api/v1/tools # List available tools
GET /api/v1/locales # List known locales (BCP-47)
POST /api/v1/projects/anonymous # Create anonymous project
Auth Routes
POST /api/v1/auth/device/start # Start device auth flow
POST /api/v1/auth/device/poll # Poll for token
POST /api/v1/auth/refresh # Token refresh
GET /api/v1/auth/login # OAuth/OIDC login redirect
GET /api/v1/auth/callback # OIDC redirect callback
GET /api/v1/auth/me # Get current user (JWT)
POST /api/v1/auth/logout # Invalidate token (JWT)
Project Routes (JWT-protected)
POST /api/v1/projects
GET /api/v1/projects
GET /api/v1/projects/:id
PUT /api/v1/projects/:id
DELETE /api/v1/projects/:id
POST /api/v1/projects/claim # Claim anonymous project
POST /api/v1/projects/:id/blocks # Store blocks
GET /api/v1/projects/:id/blocks # Retrieve blocks
POST /api/v1/projects/:id/versions # Create version snapshot
GET /api/v1/projects/:id/versions # List versions
GET /api/v1/projects/:id/changes # Get block changes
Sync Routes (JWT or ClaimToken)
POST /api/v1/projects/:id/sync/push # Push source blocks
GET /api/v1/projects/:id/sync/pull # Pull changes since cursor
GET /api/v1/projects/:id/sync/blocks # Get blocks for an item
GET /api/v1/projects/:id/sync/status # Push status (job tracking)
POST /api/v1/projects/:id/sync/translate # Create translation job
Workspace-scoped equivalents at /api/v1/workspaces/:ws/projects/:id/sync/....
Workspace Routes (require auth)
POST /api/v1/workspaces
GET /api/v1/workspaces
GET /api/v1/workspaces/:ws
PUT /api/v1/workspaces/:ws
DELETE /api/v1/workspaces/:ws
GET /api/v1/workspaces/:ws/members
POST /api/v1/workspaces/:ws/members
PUT /api/v1/workspaces/:ws/members/:uid/role
DELETE /api/v1/workspaces/:ws/members/:uid
Connector Management (workspace-scoped)
GET /api/v1/:ws/connectors # List active connectors
POST /api/v1/:ws/connectors # Add connector
PUT /api/v1/:ws/connectors/:id # Update connector
DELETE /api/v1/:ws/connectors/:id # Remove connector
GET /api/v1/:ws/connectors/:id/status # Check status
GET /api/v1/:ws/connectors/:id/content # Browse available content
POST /api/v1/:ws/connectors/:id/fetch # Fetch content via connector
POST /api/v1/:ws/connectors/:id/publish # Publish content via connector
gRPC Service Definitions
Two gRPC services are defined in bowrain/proto/v1/:
service NeokapiService {
// Project management
rpc CreateProject(CreateProjectRequest) returns (ProjectResponse);
rpc GetProject(GetProjectRequest) returns (ProjectResponse);
rpc ListProjects(ListProjectsRequest) returns (ListProjectsResponse);
rpc UpdateProject(UpdateProjectRequest) returns (ProjectResponse);
rpc DeleteProject(DeleteProjectRequest) returns (google.protobuf.Empty);
rpc CreateAnonymousProject(CreateProjectRequest) returns (ProjectResponse);
rpc ClaimProject(ClaimProjectRequest) returns (ProjectResponse);
rpc GetProjectChanges(GetChangesRequest) returns (GetChangesResponse);
// Block operations
rpc StoreBlocks(StoreBlocksRequest) returns (StoreBlocksResponse);
rpc GetBlocks(GetBlocksRequest) returns (GetBlocksResponse);
rpc StreamBlocks(StreamBlocksRequest) returns (stream BlockResponse);
// Version management
rpc CreateVersion(CreateVersionRequest) returns (VersionResponse);
rpc ListVersions(ListVersionsRequest) returns (ListVersionsResponse);
// Connector operations
rpc PullContent(PullContentRequest) returns (PullContentResponse);
rpc PushContent(PushContentRequest) returns (PushContentResponse);
// Flow execution
rpc ExecuteFlow(ExecuteFlowRequest) returns (stream FlowProgressResponse);
// Event subscription
rpc Subscribe(SubscribeRequest) returns (stream EventResponse);
}
service EditorService {
// Authentication & workspace
rpc GetCurrentUser(GetCurrentUserRequest) returns (UserResponse);
rpc ListWorkspaces(ListWorkspacesRequest) returns (ListWorkspacesResponse);
// Editor projects
rpc ListEditorProjects(ListEditorProjectsRequest) returns (ListEditorProjectsResponse);
rpc GetEditorProject(GetEditorProjectRequest) returns (EditorProjectResponse);
// Block operations
rpc GetBlocks(GetBlocksRequest) returns (GetBlocksResponse);
rpc UpdateBlockTarget(UpdateBlockTargetRequest) returns (google.protobuf.Empty);
rpc ReviewBlock(ReviewBlockRequest) returns (google.protobuf.Empty);
// Context lookups
rpc LookupMemoryForBlock(MemoryLookupRequest) returns (MemoryLookupResponse);
rpc LookupTermsForBlock(TermLookupRequest) returns (TermLookupResponse);
// Content memory and terminology CRUD
rpc GetMemoryEntries(MemoryEntriesRequest) returns (MemoryEntriesResponse);
rpc AddMemoryEntry(AddMemoryEntryRequest) returns (MemoryEntryResponse);
rpc UpdateMemoryEntry(UpdateMemoryEntryRequest) returns (google.protobuf.Empty);
rpc DeleteMemoryEntry(DeleteMemoryEntryRequest) returns (google.protobuf.Empty);
rpc GetTerms(TermsRequest) returns (TermsResponse);
rpc AddConcept(AddConceptRequest) returns (ConceptResponse);
rpc UpdateConcept(UpdateConceptRequest) returns (google.protobuf.Empty);
rpc DeleteConcept(DeleteConceptRequest) returns (google.protobuf.Empty);
// Presence & collaboration
rpc UpdatePresence(UpdatePresenceRequest) returns (google.protobuf.Empty);
rpc WatchProject(WatchProjectRequest) returns (stream ProjectEvent);
}
gRPC and REST are multiplexed on the same port via h2c (HTTP/2 cleartext). gRPC streaming enables real-time flow progress, block updates, presence tracking, and event subscriptions for the Bowrain desktop app (AD-017).
CI/CD Integration
# GitHub Actions example
- name: Pull latest translations
run: kapi pull
env:
BOWRAIN_AUTH_TOKEN: $\{{ secrets.BOWRAIN_TOKEN }}
BOWRAIN_SERVER_URL: $\{{ secrets.BOWRAIN_SERVER }}
- name: Run pseudo-translation
run: kapi pseudo-translate
- name: Push changes if tests pass
run: kapi push
env:
BOWRAIN_AUTH_TOKEN: $\{{ secrets.BOWRAIN_TOKEN }}
BOWRAIN_SERVER_URL: $\{{ secrets.BOWRAIN_SERVER }}
CI-friendly features:
--jsonflag for machine-readable output- Exit codes: 0 (success), 1 (error), 2 (conflict)
BOWRAIN_AUTH_TOKENenvironment variable (bypasses device flow login)