Summary
Add SAGEOX_TOKEN env var support so ox can authenticate in cloud/container/CI environments without interactive ox login. This is the CLI-side foundation for delivering team context to ephemeral coding sessions (Claude Code cloud, OpenClaw, etc.).
Problem
Cloud Claude Code runs in ephemeral Linux containers. On startup, hooks try to run ox agent prime but:
- ox binary isn't installed
- No way to authenticate without a browser (OAuth device flow)
- No daemon to sync team context via git
- Container is extremely minimal — may lack
git, head, even curl
Without team context, AI coworkers in cloud sessions start from zero — no architecture decisions, no conventions, no team knowledge.
What's Been Implemented (CLI Side)
Branch: ryan/ox-session-start (4 files changed, ~305 lines added)
1. SAGEOX_TOKEN env var auth (internal/auth/storage.go)
- New
EnvVarToken constant (SAGEOX_TOKEN) and tokenFromEnv() helper
- Both
GetTokenForEndpoint() functions (package-level and AuthClient method) check env var before reading from disk
- Token gets 24h rolling expiry (managed externally by whoever sets the env var)
- Works with existing
SAGEOX_ENDPOINT env var for non-production endpoints
- 5 new tests: env var overrides disk, env var with no disk token, fallback to disk,
IsAuthenticated via env var, package-level function
2. HTTP-based team context fetch (cmd/ox/agent_prime.go + internal/api/repos.go)
- New API client method:
GetTeamContextContent(teamID) calling GET /api/v1/teams/{team_id}/context
- New response types:
TeamContextContentResponse, TeamContextDoc
tryHTTPTeamContextFallback() in discoverTeamContext(): when FindRepoTeamContext() returns nil AND daemon isn't running, fetches team context via HTTP API
fetchTeamContextViaAPI(): writes fetched docs, MEMORY.md, AGENTS.md, CLAUDE.md to standard team context paths on disk
- Existing content loading code picks up the fetched files automatically
- Gracefully handles 404 (endpoint not yet implemented)
3. Response contract for GET /api/v1/teams/{team_id}/context
{
"team_id": "team_xxx",
"team_name": "SageOx",
"docs": [
{"name": "glossary.md", "title": "Glossary", "content": "..."},
{"name": "principles.md", "title": "Principles", "content": "..."}
],
"agents_md": "...",
"claude_md": "...",
"memory": "..."
}
What Still Needs Discussion
Authentication & access model for cloud sessions
The CLI assumes a SAGEOX_TOKEN JWT issued to a specific user. But cloud coding sessions raise questions:
- Who is the token issued to? The human who launched the session? A service account for the team? A per-repo bot?
- What access does the token grant? Read-only team context? Or also session recording (write)?
- Token lifecycle: How are tokens created, rotated, and revoked for cloud environments?
- Team membership: If the token belongs to a service account, what does "team membership" mean? Does the account need to be explicitly added to the team?
- Public vs private team context: Should unauthenticated access work for public teams? Or always require a token?
Backend API endpoint
The GET /api/v1/teams/{team_id}/context endpoint needs to be implemented. Decisions needed:
- Auth: Bearer token required? What scopes?
- Access check: Team membership only? Or also viewer access for public teams?
- Content selection: Serve everything, or let the client specify what it needs?
- Caching: Should responses include ETag/Cache-Control for repeated primes in the same session?
Container bootstrap
- How does the ox binary get into the container? (static binary, install script, pre-built image layer)
- Should there be an
ox cloud bootstrap command that combines init + auth + prime in one step?
Related
Files Changed
| File |
Change |
internal/auth/storage.go |
SAGEOX_TOKEN env var check in GetTokenForEndpoint() |
internal/api/repos.go |
GetTeamContextContent(teamID) client method + response types |
cmd/ox/agent_prime.go |
HTTP-based team context fallback in discoverTeamContext() |
internal/auth/storage_test.go |
5 new tests for env var token support |
Summary
Add
SAGEOX_TOKENenv var support so ox can authenticate in cloud/container/CI environments without interactiveox login. This is the CLI-side foundation for delivering team context to ephemeral coding sessions (Claude Code cloud, OpenClaw, etc.).Problem
Cloud Claude Code runs in ephemeral Linux containers. On startup, hooks try to run
ox agent primebut:git,head, evencurlWithout team context, AI coworkers in cloud sessions start from zero — no architecture decisions, no conventions, no team knowledge.
What's Been Implemented (CLI Side)
Branch:
ryan/ox-session-start(4 files changed, ~305 lines added)1.
SAGEOX_TOKENenv var auth (internal/auth/storage.go)EnvVarTokenconstant (SAGEOX_TOKEN) andtokenFromEnv()helperGetTokenForEndpoint()functions (package-level andAuthClientmethod) check env var before reading from diskSAGEOX_ENDPOINTenv var for non-production endpointsIsAuthenticatedvia env var, package-level function2. HTTP-based team context fetch (
cmd/ox/agent_prime.go+internal/api/repos.go)GetTeamContextContent(teamID)callingGET /api/v1/teams/{team_id}/contextTeamContextContentResponse,TeamContextDoctryHTTPTeamContextFallback()indiscoverTeamContext(): whenFindRepoTeamContext()returns nil AND daemon isn't running, fetches team context via HTTP APIfetchTeamContextViaAPI(): writes fetched docs, MEMORY.md, AGENTS.md, CLAUDE.md to standard team context paths on disk3. Response contract for
GET /api/v1/teams/{team_id}/context{ "team_id": "team_xxx", "team_name": "SageOx", "docs": [ {"name": "glossary.md", "title": "Glossary", "content": "..."}, {"name": "principles.md", "title": "Principles", "content": "..."} ], "agents_md": "...", "claude_md": "...", "memory": "..." }What Still Needs Discussion
Authentication & access model for cloud sessions
The CLI assumes a
SAGEOX_TOKENJWT issued to a specific user. But cloud coding sessions raise questions:Backend API endpoint
The
GET /api/v1/teams/{team_id}/contextendpoint needs to be implemented. Decisions needed:Container bootstrap
ox cloud bootstrapcommand that combines init + auth + prime in one step?Related
Files Changed
internal/auth/storage.goSAGEOX_TOKENenv var check inGetTokenForEndpoint()internal/api/repos.goGetTeamContextContent(teamID)client method + response typescmd/ox/agent_prime.godiscoverTeamContext()internal/auth/storage_test.go