Skip to content

[TEST] feat(cli): interactive menu for all commands - #127

Open
skull463 wants to merge 4 commits into
ByteBell:mainfrom
skull463:bytebell-tinker
Open

skull463 wants to merge 4 commits into
ByteBell:mainfrom
skull463:bytebell-tinker

Conversation

@skull463

@skull463 skull463 commented Jun 4, 2026

Copy link
Copy Markdown

What changed

  • Interactive menu — running bytebell-tinker (or the short bbtinker) with no arguments opens a grouped menu (Setup / Knowledge / Server / Insights). Arrow keys move, Enter runs.
  • Menu loops — after a command or form finishes you land back on the menu, so you can move back and forth between options without relaunching.
  • Navigation keysq backs out of a sub-screen to the menu; Esc leaves the TUI. (On the text-entry screens Esc backs out instead, since q is a typed character there.)
  • Configure LLM provider screen — switch OpenRouter/Ollama and set the API key + model without remembering config keys. Tab moves between fields (fixed a bug where focus was trapped on the API key and you couldn't reach/edit the Model field).
  • Connect MCP clients entry — runs mcp install to register the bytebell MCP endpoint in your editors.
  • Mode-aware setup form — when you pick Docker it shows the Mongo/Neo4j/Redis fields; when you pick Embedded it shows the SQLite/Ladybug/Queue paths. Esc returns to the menu.
  • Centralized theme — a single accent colour (theme.ts) drives every screen and the plain-stdout output (spinners, tables, progress bars), so the whole CLI is themed consistently from one place. Accent is cyan.
  • Renamed binarybytebell-tinker (plus the short bbtinker alias) so this dev build doesn't collide with an installed bytebell that only prints help.
  • Non-TUI bytebell entry — a third binary bytebell that shows commander help on bare invocation (no menu), keeping backward compatibility with scripts/aliases that expect bytebell to print subcommands.
  • Shutdown without lsofwaitForServerStopped falls back to isAlive(pid) polling on resolved target PIDs when lsof is unavailable (common on minimal Linux images), instead of returning immediately.
  • Fixes: shutdown finds the server by its listening port (a stale pid file no longer leaves it running); stats no longer crashes on older repo records; mcp stats auto-starts the server instead of erroring.
  • Merged latest main (the setup wizard + embedded-mode refactor) and resolved the conflicts.

Why

bytebell with no arguments just printed help, so you had to remember every subcommand. The menu makes the CLI discoverable and lets you bounce between actions. The dedicated provider screen removes the most common config friction, and the shutdown/stats/mcp fixes address real failures hit while testing.

The third bytebell binary keeps the old behavior (help on bare invocation) for scripts while bytebell-tinker/bbtinker drive the interactive TUI. The shutdown lsof fallback prevents the CLI from falsely reporting a clean stop on hosts without lsof.

How to test

  1. Check out this branch and install + link:
    bun install
    cd packages/cli && bun link && cd -
  2. Open the menu:
    bbtinker
    Arrow through the groups; the cyan cursor wraps. Run a command, confirm you return to the menu (loop). Press q in a sub-screen to go back, Esc to leave.
  3. bytebell non-TUI — run without arguments, confirm it prints help (not the menu):
    bytebell
  4. Configure LLM provider → choose OpenRouter → Tab down to Model → type a model → Enter to save. Re-open to confirm it persisted.
  5. Settings → Tab to Infrastructure, press ←/→: Docker shows Mongo/Neo4j/Redis, Embedded shows the SQLite/Ladybug/Queue paths.
  6. Stats / MCP usage with the server stopped → it auto-starts the server and renders the table (no "Unable to connect").
  7. Shutdown fix:
    bbtinker shutdown --keep-docker
    lsof -nP -iTCP:8080 -sTCP:LISTEN   # empty afterwards

Screenshots

Terminal render of the menu (cyan accent not shown in plain text):

╭──────────────────────────────────────────────────────────────╮
│  Bytebell Tinker                                               │
│  local knowledge engine · open-ir                              │
│                                                                │
│  SETUP                                                         │
│   ❯ ⚙  Configure LLM provider  switch openrouter/ollama · key  │
│     ⚙  Settings                infra config / setup form       │
│     ⧉  Connect MCP clients     register bytebell in your editors│
│  KNOWLEDGE                                                     │
│     ✚ Index  ⤓ Ingest  ↻ Pull  ≡ List  ✕ Delete               │
│  SERVER                                                        │
│     ▲ Boot   ■ Shutdown                                        │
│  INSIGHTS                                                      │
│     ▤ Stats   ◷ MCP usage                                     │
╰──────────────────────────────────────────────────────────────╯
   ↑ ↓  navigate    ⏎  run    esc  quit                   v0.0.0

Non-TUI bytebell help output:

Usage: bytebell [options] [command]

Bytebell Tinker — local knowledge engine TUI
...

@bharatsachya

Copy link
Copy Markdown
Contributor

Pull Request Guide

Follow these conventions so every PR is easy to navigate, review, and merge.


1. Branch Naming

General rules

  • Descriptive: use clear, concise names that describe the purpose of the branch.
  • Lowercase only: no uppercase letters.
  • Hyphens to separate words: no spaces, no underscores.
  • No special characters: avoid !, @, #, $, %, etc.
  • Always prefix with the type of work (see below).

Branch prefixes

Prefix When to use Example
feature/ New features or enhancements feature/user-authentication
bugfix/ Bug fixes bugfix/login-issue
hotfix/ Critical fixes that must ship immediately hotfix/payment-gateway-error
improvement/ Non-feature improvements (refactors, perf) improvement/refactor-auth-module
release/ Release prep release/v1.2.0
chore/ Maintenance: dependencies, configs, tooling chore/update-dependencies
docs/ Documentation-only changes docs/update-readme

2. PR Title

Every PR title must start with a status tag followed by the branch purpose.

Status tags

Tag Meaning
[WIP] Work in progress — do not merge yet. Reviewers may skim but not approve.
[TEST] Ready for review and testing. Feedback welcome; not yet merge-ready.
[DONE] Reviewed, tested, and ready to merge.

Update the tag as the PR progresses — move from [WIP][TEST][DONE].

Examples

  • [WIP] feature/user-authentication — initial Bitbucket OAuth wiring
  • [TEST] bugfix/login-issue — fix wrong org routing on re-login
  • [DONE] chore/update-dependencies — bump fastify to 5.6
  • [DONE] docs/update-readme

3. PR Description

Every PR description must include these sections:

What changed

A clear bulleted list of the concrete changes. Not a copy of the commit log — a human-readable summary.

Why

The reason for the change. Link the ticket / issue / conversation that prompted it. If it's a bug fix, describe the bug.

How to test

Step-by-step instructions a reviewer can follow to verify the change end-to-end. Include:

  • Commands to run
  • Endpoints to hit / UI flows to exercise
  • Expected results

Screenshots (frontend PRs only)

Required for any PR that touches UI. Include:

  • Before screenshot of the current UI (omit for brand-new UI)
  • After screenshot showing the PR's result
  • For multi-state UIs (loading / empty / error / success), show each state
  • For responsive changes, show both desktop and mobile widths

Use the GitHub image upload (drag and drop into the description box) — do not link to external image hosts.


4. Example PR Description

## What changed

- Added `CreatedByBadge` component shared between Feedback and Chats pages
- Role-gated the badge to org admins only via `useAuth` hook
- Added `user_role` to the login response so the frontend can determine admin status

## Why

Org admins need to see who authored each feedback/chat entry for accountability.
Regular users always see their own content, so the createdBy chip is redundant for them.

Linked issue: #142

## How to test

1. Log in as `admin_user@emai.com` (role: `admin`)
2. Open `http://localhost/deadbytes-org/feedback?page=1` — avatar chip should appear on rows with a `createdBy`
3. Open `http://localhost/deadbytes-org/chats?page=1` — same behaviour
4. Log in as a regular user — the chip should NOT appear on either page

## Screenshots

### Feedback page — admin view

[screenshot-admin-feedback.png]

### Feedback page — regular user view

[screenshot-user-feedback.png]

5. Checklist Before Marking [DONE]

  • Branch name follows the naming rules above
  • Title starts with a status tag
  • Description has What / Why / How to test sections
  • Screenshots attached (frontend PRs only)
  • All CI checks pass (formatting, build, tests)
  • Self-reviewed the diff — no leftover debug logs, commented-out code, or secrets
  • Rebased against the target branch so the diff is clean

Thanks for keeping the review process fast and the git history readable.

Here you go this is template for PR description

@bharatsachya

Copy link
Copy Markdown
Contributor

Also please resolve your conflicts

Resolves conflicts between the interactive TUI menu work and main's new
setup wizard / serverLifecycle (embedded-mode) refactor:

- index.ts/program.ts: keep the menu-based entry, register main's new
  `setup` command.
- ShutdownCommand: take main's stopServer()-based structure; relocate the
  port-based stale-pid fix into serverLifecycle.stopServer() so it still
  applies under the refactor.
- READMEs/bun.lock: merge both sides, de-dupe main's command table.

Post-merge menu updates:
- Add "Connect MCP clients" (mcp install) to the menu.
- Boot hint notes infra is brought up only when needed (embedded mode).
- mcp stats now ensureServerRunning() first, matching stats/ls (fixes
  "Unable to connect" when the server is down).
- Drop the one-time `setup` wizard from the menu (still a CLI command).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@skull463 skull463 changed the title feat: added an interactive TUI menu for all comands [TEST] feat(cli): interactive menu for all commands Jun 4, 2026
@bharatsachya
bharatsachya self-requested a review June 5, 2026 07:23

@bharatsachya bharatsachya left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1.Theme should be centralised and it should work for all the commands
2.Add a back command to go back and forth between options
3. replace bytebell with bytebell set as bytebell shows helper command

- Menu now loops: every command/form returns to the menu so you move
  back and forth between options. `q` backs out of a sub-screen, `Esc`
  leaves the TUI.
- Centralize the accent in theme.ts (ACCENT + ANSI) and apply it to the
  plain-stdout path (output.ts spinners, tables, progress bars) so the
  theme covers every command, Ink or not.
- Rename the binary to `bytebell-tinker` (avoids colliding with an
  installed `bytebell` that only prints help) plus a short `bbtinker`
  alias; program name + menu header updated to "Bytebell Tinker".
- Setup form is mode-aware: Docker shows the Mongo/Neo4j/Redis fields,
  Embedded shows the SQLite/Ladybug/Queue paths; Esc returns to the menu.
- Fix: the LLM provider form double-handled Tab on top of Ink's focus
  manager, trapping focus on the API key — now Tab reaches and edits the
  Model field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@skull463
skull463 requested a review from bharatsachya June 5, 2026 17:51
@bharatsachya
bharatsachya requested a review from ankitzm June 8, 2026 05:26

@bharatsachya bharatsachya left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bytebell is still showing menu revert it back to older version


/** Pids holding a LISTEN socket on the given TCP port, via `lsof`. Returns
* `[]` when lsof is absent or finds nothing — callers degrade gracefully. */
function findListenerPids(port: number): Promise<number[]> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findListenerPids() returns [] whenever lsof is missing or errors (by design, "degrade gracefully"). But waitForServerStopped() is built entirely on findListenerPids, so on a host without lsof it returns true immediately — stopServer sends SIGTERM, unlinks the pid file, and reports a clean stop without ever confirming the process is down. The old code waited for the pid file to vanish, which was weaker but at least waited. macOS (the stated platform) ships lsof, but the CLI is distributed cross-platform and minimal Linux images frequently lack it. Consider falling back to isAlive(pid)-polling on the resolved target pids when findListenerPids yields nothing.

Comment thread packages/cli/package.json
},
"bin": {
"bytebell": "./src/index.ts"
"bytebell-tinker": "./src/index.ts",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no you cannot change this

@skull463 skull463 closed this Jun 9, 2026
@skull463
skull463 deleted the bytebell-tinker branch June 9, 2026 14:12
@skull463
skull463 restored the bytebell-tinker branch June 9, 2026 14:13
@skull463 skull463 reopened this Jun 9, 2026
@skull463
skull463 requested a review from bharatsachya June 9, 2026 15:51
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.

2 participants