Skip to content

feat(cli): non-interactive init, REPL chat, project link, beefier doctor#521

Merged
buremba merged 6 commits into
mainfrom
claude/lobu-command-ux-analysis-Obi5t
May 4, 2026
Merged

feat(cli): non-interactive init, REPL chat, project link, beefier doctor#521
buremba merged 6 commits into
mainfrom
claude/lobu-command-ux-analysis-Obi5t

Conversation

@buremba
Copy link
Copy Markdown
Member

@buremba buremba commented May 4, 2026

Summary

Closes the largest UX gaps in the lobu CLI relative to comparable tools (Wrangler, Convex, Vercel, Stripe CLI). Each change addresses a concrete foot-gun rather than adding new surface for its own sake.

lobu init

  • --yes plus per-prompt flags (--port, --public-url, --network, --provider, --provider-key, --platform, --memory, --memory-url, --otel-endpoint, --sentry/--no-sentry) so init can run unattended / in CI.
  • lobu init . / --here scaffolds into the current directory; bails if it would clobber an existing lobu.toml / agents/ / .env.
  • Sentry now defaults to off (was opt-in true). lobu telemetry {status,on,off} toggles SENTRY_DSN in .env afterwards.
  • Next-steps prints a Docker pgvector one-liner and a real DATABASE_URL template instead of a Mac-only brew hint.
  • Recovery messages standardized on lobu <cmd> (drops the inconsistent npx @lobu/cli@latest … mix).

lobu run (with dev / start aliases)

  • Pre-flights the gateway port and prints a platform-specific lsof / netstat hint when busy, instead of letting the bundle dump EADDRINUSE.
  • --port, --quiet, --verbose, --log-level forwarded to the bundle.

lobu chat

  • No prompt → REPL bound to the agent session, with /exit, /help, /thread, /clear slash-commands and per-(context, agent) thread persistence in ~/.config/lobu/threads.json.
  • --continue resumes the last thread; --auto-approve skips tool prompts for trusted runs; --json emits raw SSE events for piping.

lobu doctor

  • Adds Postgres connectivity, pgvector extension presence, gateway port availability, provider API keys (cross-referenced against lobu.toml), and workspace dir checks. Driver pulled from the postgres package already on the dependency list.

lobu apply (alias: deploy)

  • .lobu/project.json binds a directory to a (context, org). lobu link / lobu unlink manage it, and apply refuses mismatched targets unless --force. Mirrors vercel link / convex dev.

Scaffolders

  • lobu agent scaffold <id> adds a second/third agent + lobu.toml block.
  • lobu eval new <name> writes a YAML eval template into the agent's evals/ directory.

Discovery

  • lobu --help now groups commands by Local dev / Cloud / Memory.
  • One npm-registry version check per 24h prints a stderr nudge when a newer @lobu/cli is published. LOBU_DISABLE_UPDATE_CHECK=1 opts out.

Out of scope (each is its own concern)

  • Hot reload in lobu run (would need file watcher + restart wrapper around the bundle).
  • Tunnel integration for OAuth/webhook callbacks (Stripe CLI–style cloudflared/ngrok wrapping).
  • lobu logs <agentId> --tail for cloud-deployed agents (needs a server-side log endpoint).

These are tracked as follow-up PRs.

Test plan

  • bun test in packages/cli — 95 pass, 0 fail (11 new tests in cli-ux.test.ts covering init --yes / --here / --sentry / bad --provider, project-link round-trip + .gitignore de-dup, agent scaffold TOML appending, eval new YAML output, isPortFree both states).
  • make build-packages — clean build of all workspace packages.
  • bun run typecheck — clean.
  • Smoke test: node packages/cli/bin/lobu.js init smoke --yes produces a valid project with no prompts; lobu --help shows grouped sections; existing 84 tests still pass.
  • Manual: try lobu chat (REPL), lobu chat -C (resume), lobu link/apply mismatch path against a real org.
  • Manual: lobu doctor against a fresh project with no DATABASE_URL → expect actionable fail messages.

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd


Generated by Claude Code

Closes the largest UX gaps in the lobu CLI relative to comparable tools
(Wrangler, Convex, Vercel, Stripe CLI). Each change addresses a concrete
foot-gun rather than adding new surface for its own sake.

init
- `--yes` plus per-prompt flags (`--port`, `--public-url`, `--network`,
  `--provider`, `--provider-key`, `--platform`, `--memory`, `--memory-url`,
  `--otel-endpoint`, `--sentry`/`--no-sentry`) so init can run unattended.
- `lobu init .` / `--here` scaffolds into the current directory; bails if
  it would clobber an existing lobu.toml/agents/.env.
- Sentry now defaults to off (was opt-in true). `lobu telemetry {status,on,off}`
  toggles SENTRY_DSN in .env after the fact.
- Next-steps prints a Docker pgvector one-liner and a real DATABASE_URL
  template instead of a Mac-only brew hint.
- Recovery messages standardized on `lobu <cmd>` (drops the `npx
  @lobu/cli@latest` mix).

run (with `dev` / `start` aliases)
- Pre-flights the gateway port and prints the platform-specific lsof/netstat
  hint when busy, instead of letting the bundle dump EADDRINUSE.
- `--port`, `--quiet`, `--verbose`, `--log-level` forwarded to the bundle.

chat
- No prompt -> REPL bound to the agent session, with /exit, /help, /thread,
  /clear slash-commands and per-(context, agent) thread persistence in
  ~/.config/lobu/threads.json.
- `--continue` resumes the last thread; `--auto-approve` skips tool prompts
  for trusted runs; `--json` emits raw SSE events for piping.

doctor
- Adds Postgres connectivity, pgvector extension presence, gateway port
  availability, provider API keys (cross-referenced against lobu.toml),
  and workspace dir checks. Driver pulled from the `postgres` package
  already on the dependency list.

apply (alias: deploy)
- `.lobu/project.json` binds a directory to a (context, org). `lobu link`
  / `lobu unlink` manage it, and `apply` refuses mismatched targets unless
  `--force` is set. Mirrors `vercel link` / `convex dev`.

scaffolders
- `lobu agent scaffold <id>` adds a second/third agent + lobu.toml block.
- `lobu eval new <name>` writes a YAML eval template into the agent's
  evals/ directory.

discovery
- `lobu --help` now groups commands by Local dev / Cloud / Memory.
- One npm-registry version check per 24h prints a stderr nudge when a
  newer @lobu/cli is published. `LOBU_DISABLE_UPDATE_CHECK=1` opts out.

Tests cover init --yes, --here, --sentry, project-link round-trip + .gitignore
de-dup, agent scaffold's TOML appending, eval new YAML output, and isPortFree's
two states. CLI tests pass (95). Out of scope (each is its own concern):
hot reload, tunnel integration, `lobu logs` for cloud agents.

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Picks up the formatter changes the pre-commit hook applied during the
previous commit but that didn't make it into the final tree.

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
// "EADDRINUSE" foot-gun before the bundle boots and dumps a stack.
const portFree = await isPortFree(Number(port));
if (!portFree) {
console.error(chalk.red(`\n Port ${port} is already in use.`));
Comment on lines +108 to +112
chalk.dim(
process.platform === "darwin" || process.platform === "linux"
? ` Find what's holding it: lsof -iTCP:${port} -sTCP:LISTEN\n`
: ` Find what's holding it: netstat -ano | findstr :${port}\n`
)
console.log(
chalk.dim(` database: ${redactUrl(mergedEnv.DATABASE_URL!)}`)
);
console.log(chalk.dim(` api docs: ${gatewayUrl}/api/docs`));
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 4, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 61.46927% with 257 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/cli/src/commands/init.ts 57.52% 127 Missing ⚠️
packages/cli/src/commands/chat.ts 61.24% 50 Missing ⚠️
packages/cli/src/commands/dev.ts 20.63% 50 Missing ⚠️
packages/cli/src/commands/agent.ts 84.14% 13 Missing ⚠️
packages/cli/src/commands/eval.ts 75.51% 12 Missing ⚠️
packages/cli/src/internal/project-link.ts 93.02% 3 Missing ⚠️
packages/cli/src/internal/context.ts 0.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added the triage:needs-human Triage agent escalated for human review label May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Triage decision: needs-human

Reasons:

  • PR size exceeds auto-merge threshold (2,409 lines, 17 files; limits 300 lines, 10 files)
  • Failed CI checks: pr-size validation failed, CodeQL analysis failed
  • PR is otherwise well-structured CLI feature enhancement but requires manual review due to size

Next: Manual review and merge by maintainer after addressing any CI failures

claude added 2 commits May 4, 2026 15:38
Audit pass on the previous commit. Cuts what wasn't earning its keep
and hardens what stayed. Net -347 lines.

Removed
- internal/version-check.ts (npm-registry update notifier on every
  command). Adds 24h fetch traffic + ~/.config/lobu state for marginal
  benefit; users already type `npx @lobu/cli@latest`. Out of PR scope.
- internal/threads.ts (single caller). Inlined into chat.ts as ~25
  lines, dropping a module + an interface that didn't need to exist.
- linkStatusCommand (declared but never wired into commander).
- REPL slash-commands /help, /thread, /clear. Kept /exit (and /quit
  alias). The dropped ones were nice-to-have, not requested.

Hardened
- doctor.ts: replaced `postgres: any` / `sql: any` with proper
  generics on the postgres tag. Collapsed three try/catch blocks to
  the actually-needed two; .end() failures now use .catch instead of
  swallowing try-blocks.
- run: dropped helpOption(false) + allowUnknownOption(true). The
  command now takes only its own flags, so `lobu run --help` works
  (was a regression exposed by the dev/start aliases).
- init: hoisted the --memory owletto-custom + --memory-url validation
  to the top so a bad combo doesn't leave a half-created project dir
  behind. Removed the no-longer-reachable second check.
- run: forwards LOG_LEVEL only, not LOG_LEVEL + LOBU_LOG_LEVEL. The
  second was speculative cargo.

Trimmed
- init's next-steps printing: replaced the stepNum/cdHint dance with
  a single counter. Same information, half the lines.
- README.md: dropped the per-flag tables; `lobu --help` and `lobu
  <cmd> --help` cover those. Top-level overview only.
- Comments: section dividers and past-tense ("Sentry now defaults to
  OFF") removed per CLAUDE.md.

Tests: 106 pass. Smoke verified `lobu init --yes`, `lobu --help`,
`lobu run --help`, `lobu start --help`.

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
Bugs
- agent.ts: --name was interpolated raw into TOML, so a name like
  Sales "Bot" v2 produced an invalid file. Now uses JSON.stringify, same
  as the description field. Test added.
- dev.ts: a non-numeric --port (e.g. --port abc) reached
  net.createServer().listen({ port: NaN }), which we then misreported as
  "port in use" via the catch path. Now validates 1-65535 up front.

Dead / over-engineered
- dev.ts: dropped the `passthroughArgs` parameter; the run command no
  longer takes unknown options after the helpOption(false) removal.
- index.ts: dropped the `sentryProvided` indirection. Commander already
  gives a tristate (true/false/undefined), so `=== true` / `=== false`
  is enough; the helper boolean was redundant.
- init.ts: replaced the 30-line `scaffoldPlatformConfigPlaceholders`
  function with a 13-line static map. Same output, no switch/case.
- project-link.ts: unexported PROJECT_LINK_DIR / PROJECT_LINK_FILE
  (only used internally) and folded the unlink path into
  removeProjectLink so link.ts doesn't hardcode the file location.
- apply-cmd.ts, agent.ts, eval.ts: collapsed multi-line docstrings and
  speculative comments per CLAUDE.md ("default to no comments;
  one-liner max").
- telemetry.ts: stopped truncating the Sentry public key — it's
  embedded in client-side JS, redacting it just hides info from the
  user without security benefit.

Tests: 106 pass, +1 covering the TOML-escape regression.
https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
options.port ?? mergedEnv.GATEWAY_PORT ?? mergedEnv.PORT ?? "8787";
const portNum = Number(port);
if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) {
console.error(chalk.red(`\n Invalid port "${port}" — must be 1-65535.\n`));
claude added 2 commits May 4, 2026 21:07
The CLI's primary callers are coding agents (Codex / Claude Code /
Aider) and CI scripts, both of which drive it as one-shot. A REPL
optimizes for humans typing into a tty, which isn't what `lobu chat`
is for.

Removed
- runRepl + ReplOptions (~75 lines)
- The `if (prompt === undefined)` branch in chatCommand
- The "Type your message. Ctrl+D or /exit to quit." banner
- `chat [prompt]` -> `chat <prompt>` (commander rejects missing arg)

Kept
- --continue / thread persistence in ~/.config/lobu/threads.json:
  still useful for one-shot follow-ups (`lobu chat "..." -C`).
- --auto-approve, --json, --new, --thread.
- The tool-approval readline prompt (still used inline mid-stream).

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
Non-informational greeting; agents (the primary CLI consumer) just
parse for completion + path. The "✓ Lobu initialized!" line still
signals success.

https://claude.ai/code/session_01KiUnJEGTUUrrywc5Nsftnd
@buremba buremba merged commit 1b02761 into main May 4, 2026
12 of 15 checks passed
@buremba buremba deleted the claude/lobu-command-ux-analysis-Obi5t branch May 4, 2026 21:17
buremba added a commit that referenced this pull request May 4, 2026
## Round 1 (10 agents)
- `refactor!: drop deprecated ScoringConfig from connector-sdk` (BREAKING — release-please will major-bump)
- Remove deprecated owletto-* npm shim packages (5 packages, source removed; v6.0.1 stays published with deprecation notices)
- Inline gateway barrels: auth/{chatgpt,gemini,settings}, {api,channels,spaces}, connections, proxy/egress-judge
- Consolidate retry utilities → @lobu/core (drop p-retry from connector-sdk)
- Route connector-sdk logger through @lobu/core (drop pino from connector-sdk)
- Consolidate test setup fixtures (5 dead factories deleted, test-workspace.ts merged)
- Simplify gateway/connections re-exports + platform-auth-methods wrapper

## Round 2 (15 agents, 3 NO-OPs)
- Remove unused `notify` admin tool
- Simplify @lobu/connector-worker barrel (drop public exports + tsconfig path alias)
- Consolidate OAuth scope utilities (utils/oauth-scopes → auth/oauth/scopes)
- Inline orchestration/impl, lobu/stores, identity/connectors, cli apply barrels
- Unify reserved-slug list (RESERVED_PATHS + RESERVED_SLUGS → 27 entries)
- Remove unused cli/internal exports
- Consolidate JSON utilities into @lobu/core
- Inline connector-worker types barrel
- Deduplicate validateEmbeddingDimensions
- Skipped (live code): feed-sync.ts (cross-workspace import), embeddings/{server,openai}.ts (forked at runtime), @lobu/connectors barrel (public API)

## Round 3 (8 agents, 1 NO-OP)
- **Remove 45 unused deps from @lobu/cli** (drops AWS, OpenTelemetry, React, Hono, Sentry, Winston transitive trees)
- Remove 14 orphan npm scripts from root package.json (32 → 18)
- Fix two broken cross-repo imports (web submodule, sibling owletto repo)
- Relocate smol-toml from server to root devDeps
- Remove unused gateway barrel (68 lines, 0 importers)
- Remove unused server exports (findMemberEntityIdByIdentities + 7 others)
- Remove unused cli exports (PLATFORM_LABELS + dead re-exports)
- Skipped (live code): jimp/sharp in connector-worker (intentional runtime-resolved deps for compiled connectors)

## Validation
- Lint, format, typecheck: clean
- Root unit tests: 283 pass / 0 fail / 21 skip
- Server vitest: same flaky pre-existing failures as main (no PR-introduced regressions)
- CLI smoke: all subcommands resolve and respond to --help (including new `link`/`doctor` from #521)

## Heads-up for reviewers
- `refactor!: drop deprecated ScoringConfig` triggers a major version bump on @lobu/connector-sdk via release-please.
- @lobu/connector-sdk now transitively pulls Winston/Sentry/OTel/zod via @lobu/core; downstream connector authors pay that cost.
- Owletto-shim source removal is a one-way door: cannot ship fixes for v6.0.1 of those 5 deprecated packages.
buremba pushed a commit that referenced this pull request May 4, 2026
Sweeps a handful of unresolved review threads on already-merged PRs.

- task-scheduler (#478): retry seedNextCronTick in the background after
  boot-time failures so a transient DB hiccup doesn't permanently idle a
  periodic task until the next pod restart.

- mcp/proxy (#498): forward the worker JWT into getToolAnnotations so
  internal MCP tool discovery (lobu-memory) doesn't go upstream
  unauthenticated, return empty, and silently bypass requiresToolApproval.

- mcp/config-service (#498): preserve a manually configured lobu-memory
  MCP entry when deriveLobuMemoryServer returns null (transient DB error).
  Only drop entries that were derived (internal === true).

- cli/dev (#521): clear CodeQL clear-text-logging alerts by logging the
  validated portNum instead of the raw env-sourced port string.
buremba added a commit that referenced this pull request May 5, 2026
#535)

* fix: address unaddressed Codex P1/P2 review comments from recent PRs

Sweeps a handful of unresolved review threads on already-merged PRs.

- task-scheduler (#478): retry seedNextCronTick in the background after
  boot-time failures so a transient DB hiccup doesn't permanently idle a
  periodic task until the next pod restart.

- mcp/proxy (#498): forward the worker JWT into getToolAnnotations so
  internal MCP tool discovery (lobu-memory) doesn't go upstream
  unauthenticated, return empty, and silently bypass requiresToolApproval.

- mcp/config-service (#498): preserve a manually configured lobu-memory
  MCP entry when deriveLobuMemoryServer returns null (transient DB error).
  Only drop entries that were derived (internal === true).

- cli/dev (#521): clear CodeQL clear-text-logging alerts by logging the
  validated portNum instead of the raw env-sourced port string.

* style(cli/dev): apply biome line-wrap for invalid-port error

Pre-commit hook reformat that was missed in the prior commit.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:needs-human Triage agent escalated for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants