-
Notifications
You must be signed in to change notification settings - Fork 968
New cli update #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New cli update #107
Changes from all commits
f975e3a
613895c
c6ba47d
a6277f1
fd0fbf2
11f6dfe
9e20bb6
64fbac1
d75f92e
8eec9bf
f928f75
16cdcbf
0b79f09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| CLAUDE.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,66 @@ | ||
| # CLI | ||
| # Superset CLI | ||
|
|
||
| To run this, have 2 processes: | ||
| CLI for managing environments, workspaces (git worktrees/cloud branches), agents, and changes. Built with Ink + Commander, storage via lowdb JSON. | ||
|
|
||
| The first one is the build process: | ||
| ``` | ||
| bun dev | ||
| ``` | ||
| ## Quick start (dev) | ||
| - Install deps: `bun install` | ||
| - Dev watch: `bun dev` (builds to `dist/`) | ||
| - Run CLI from source: `bunx ts-node src/cli.tsx --help` | ||
| Or from build: `bun run build && bun start …` | ||
| - Binary name: `superset` (points to `dist/cli.js`) | ||
|
|
||
| The 2nd one runs the actual dev "server" | ||
| ``` | ||
| bun start | ||
| ``` | ||
| ## Core concepts | ||
| - **Environment**: grouping for workspaces (default env seeded). | ||
| - **Workspace**: local or cloud. For local, include `--path`; for cloud, include `--branch`. Tracks `defaultAgents`, `lastUsedAt`, `current workspace` pointer. | ||
| - **Worktree**: modelled as a workspace in CLI (one repo path/branch per workspace; dedicated worktree creation helpers are TODO). | ||
| - **Agent**: tmux-backed interactive session (Claude/Codex/Cursor). Each agent has a `sessionName`; `agent start` launches tmux sessions, `agent attach`/dashboard Enter attaches; detach with `Ctrl-b d`. | ||
| - **Change**: change log per workspace; has file diffs. | ||
|
|
||
| ## Common commands | ||
| - `superset init` – Wizard to create workspace (local/cloud), set name/path/branch, choose default agents, set current workspace. | ||
| - `superset dashboard` – Ink dashboard; shows workspaces/agents, press Enter on an agent to attach to its tmux session; use `q/ESC` to exit. | ||
| - `superset workspace list|get|create|delete|use` | ||
| - Local: `workspace create <envId> local --path <path>` | ||
| - Cloud: `workspace create <envId> cloud --branch <ref>` | ||
| - `workspace use <id>` sets current workspace. | ||
| - `superset env list|get|create|delete` | ||
| - `superset agent start [workspaceId]` – Uses current workspace if omitted; starts default agents if configured. | ||
| - `superset agent attach <agentId|sessionName>` – Attach to tmux session. Detach with `Ctrl-b d`. | ||
| - `superset agent list|get|stop <id>|stop-all [--workspace <id>]|delete <id>` – `stop-all` only stops agents and kills their tmux sessions. | ||
| - `superset change list <workspaceId>|create <workspaceId> "<summary>"|delete <id>` | ||
|
|
||
| ## tmux integration | ||
| - Requires `tmux` installed and on PATH. | ||
| - Sessions are named `agent-<shortId>` unless overridden in storage. | ||
| - Launch commands resolve from agent `launchCommand`, env overrides `SUPERSET_AGENT_LAUNCH_<TYPE>`, or defaults (`claude`, `codex`, `cursor`). | ||
| - To customize: `export SUPERSET_AGENT_LAUNCH_CLAUDE="your-custom-command"` (similarly for `CODEX`, `CURSOR`) | ||
| - Ensure the command stays alive (doesn't exit immediately) to prevent tmux session failures. | ||
| - If a session exists, attach; otherwise create detached then attach. Detach with `Ctrl-b d` to return to the dashboard/CLI; agents continue running. | ||
| - `stop/stop-all` issue `tmux kill-session` and mark agent stopped. | ||
|
|
||
| ## Storage | ||
| - lowdb JSON at `~/.superset/cli/db.json` (default), seeded with a `default` environment and `state.currentWorkspaceId`. | ||
| - Can be overridden with `SUPERSET_CLI_DATA_DIR` environment variable. | ||
| - Dates are serialized ISO strings; orchestrators backfill defaults and persist missing fields (status, launchCommand, sessionName, timestamps). | ||
|
|
||
| ## Security & Configuration Notes | ||
|
|
||
| ### Session Names | ||
| - Session names are generated internally as `agent-<shortId>` (6-char UUID prefix). | ||
| - Only alphanumeric, hyphen, and underscore characters are allowed in tmux session names. | ||
| - If custom session names are added in the future, they will be sanitized to meet tmux requirements. | ||
|
|
||
| ### Launch Commands | ||
| - Agent launch commands are executed exactly as provided in environment variables or config. | ||
| - **Security**: Only use trusted commands. The CLI does not sanitize or escape launch commands. | ||
| - **Best practice**: Use binaries on PATH (e.g., `claude`, `codex`) rather than complex shell expressions. | ||
| - **Complex shells**: For wrapped commands or environment setup, set `SUPERSET_AGENT_LAUNCH_<TYPE>` to point to a single, well-known entrypoint script: | ||
| ```bash | ||
| export SUPERSET_AGENT_LAUNCH_CLAUDE="/usr/local/bin/launch-claude.sh" | ||
| ``` | ||
| Then put your complex logic in that script. | ||
| - **Command validation**: Simple commands (1-2 words) are checked for existence on PATH. Complex commands (with quotes, env vars, or multiple arguments) skip preflight validation to avoid false negatives. | ||
|
|
||
| ## Tips | ||
| - Use `superset` (no args) for a welcome summary and quick commands. | ||
| - If attach fails, ensure tmux is installed and the agent has a valid `launchCommand` (set env `SUPERSET_AGENT_LAUNCH_CLAUDE=claude` etc.). | ||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -3,23 +3,29 @@ import { Command } from "commander"; | |||
| import { render } from "ink"; | ||||
| import React from "react"; | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainRemove unused
-import React from "react";Assuming your TS config uses the modern JSX transform ( 🏁 Script executed: #!/bin/bash
# Verify React import and usage in cli.tsx
echo "=== Examining apps/cli/src/cli.tsx ==="
cat apps/cli/src/cli.tsx | head -20
echo ""
echo "=== Searching for 'React' references in file ==="
rg -n 'React' apps/cli/src/cli.tsx || echo "No React references found"
echo ""
echo "=== Checking for JSX syntax ==="
rg -n 'JSX|<[A-Z]|</' apps/cli/src/cli.tsx | head -10Length of output: 927 Remove unused Verified: -import React from "react";📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Actions: CI[warning] 4-4: lint/correctness/noUnusedImports: Unused import React detected. 🤖 Prompt for AI Agents |
||||
| import { | ||||
| AgentAttach, | ||||
| AgentCreate, | ||||
| AgentDelete, | ||||
| AgentGet, | ||||
| AgentList, | ||||
| AgentStart, | ||||
| AgentStop, | ||||
| AgentStopAll, | ||||
| ChangeCreate, | ||||
| ChangeDelete, | ||||
| ChangeList, | ||||
| Dashboard, | ||||
| EnvCreate, | ||||
| EnvDelete, | ||||
| EnvGet, | ||||
| EnvList, | ||||
| Init, | ||||
| Panels, | ||||
| WorkspaceCreate, | ||||
| WorkspaceDelete, | ||||
| WorkspaceGet, | ||||
| WorkspaceList, | ||||
| WorkspaceUse, | ||||
| } from "./commands/index"; | ||||
| import { AgentType, ProcessType } from "./types/process"; | ||||
| import { WorkspaceType } from "./types/workspace"; | ||||
|
|
@@ -33,8 +39,34 @@ program | |||
| ) | ||||
| .version("0.1.0"); | ||||
|
|
||||
| // Init command | ||||
| program | ||||
| .command("init") | ||||
| .description("Interactive workspace creation wizard") | ||||
| .action(() => { | ||||
| render(<Init />); | ||||
| }); | ||||
|
|
||||
| // Dashboard command | ||||
| program | ||||
| .command("dashboard") | ||||
| .description("Show dashboard with all agents and workspaces") | ||||
| .action(() => { | ||||
| render(<Dashboard />); | ||||
| }); | ||||
|
|
||||
| // Panels command | ||||
| program | ||||
| .command("panels") | ||||
| .description("Show three-panel IDE-style interface") | ||||
| .action(() => { | ||||
| render(<Panels />); | ||||
| }); | ||||
|
|
||||
| // Environment commands | ||||
| const env = program.command("env").description("Manage environments"); | ||||
| const env = program | ||||
| .command("env") | ||||
| .description("Manage environments (list, get, create, delete)"); | ||||
|
|
||||
| env | ||||
| .command("list") | ||||
|
|
@@ -69,7 +101,9 @@ env | |||
| }); | ||||
|
|
||||
| // Workspace commands | ||||
| const workspace = program.command("workspace").description("Manage workspaces"); | ||||
| const workspace = program | ||||
| .command("workspace") | ||||
| .description("Manage workspaces (list, get, create, use, delete)"); | ||||
|
|
||||
| workspace | ||||
| .command("list") | ||||
|
|
@@ -128,10 +162,20 @@ workspace | |||
| render(<WorkspaceDelete id={id} onComplete={() => process.exit(0)} />); | ||||
| }); | ||||
|
|
||||
| workspace | ||||
| .command("use") | ||||
| .description("Set current workspace (updates lastUsedAt)") | ||||
| .argument("<id>", "Workspace ID") | ||||
| .action((id: string) => { | ||||
| render(<WorkspaceUse id={id} onComplete={() => process.exit(0)} />); | ||||
| }); | ||||
|
|
||||
| // Agent/Process commands | ||||
| const agent = program | ||||
| .command("agent") | ||||
| .description("Manage agents and processes"); | ||||
| .description( | ||||
| "Manage agents and processes (start, stop, stop-all, list, delete)", | ||||
| ); | ||||
|
|
||||
| agent | ||||
| .command("list") | ||||
|
|
@@ -154,6 +198,24 @@ agent | |||
| render(<AgentGet id={id} onComplete={() => process.exit(0)} />); | ||||
| }); | ||||
|
|
||||
| agent | ||||
| .command("start") | ||||
| .description( | ||||
| "Start agents (uses current workspace if no ID provided, or workspace's default agents)", | ||||
| ) | ||||
| .argument("[workspaceId]", "Workspace ID (optional, uses current workspace)") | ||||
| .action((workspaceId?: string) => { | ||||
| render(<AgentStart workspaceId={workspaceId} />); | ||||
| }); | ||||
|
|
||||
| agent | ||||
| .command("attach") | ||||
| .description("Attach to an agent's tmux session") | ||||
| .argument("<id>", "Agent ID or session name (e.g., agent-abc123)") | ||||
| .action((id: string) => { | ||||
| render(<AgentAttach id={id} onComplete={() => process.exit(0)} />); | ||||
| }); | ||||
|
|
||||
| agent | ||||
| .command("create") | ||||
| .description("Create a new agent/process") | ||||
|
|
@@ -208,9 +270,17 @@ agent | |||
|
|
||||
| agent | ||||
| .command("stop-all") | ||||
| .description("Stop all agents/processes") | ||||
| .action(() => { | ||||
| render(<AgentStopAll onComplete={() => process.exit(0)} />); | ||||
| .description( | ||||
| "Stop all agents in workspace (kills tmux sessions, does not affect terminals)", | ||||
| ) | ||||
| .option("--workspace <workspaceId>", "Workspace ID to stop agents in") | ||||
| .action((options: { workspace?: string }) => { | ||||
| render( | ||||
| <AgentStopAll | ||||
| workspaceId={options.workspace} | ||||
| onComplete={() => process.exit(0)} | ||||
| />, | ||||
| ); | ||||
| }); | ||||
|
|
||||
| agent | ||||
|
|
@@ -222,7 +292,9 @@ agent | |||
| }); | ||||
|
|
||||
| // Change commands | ||||
| const change = program.command("change").description("Manage changes"); | ||||
| const change = program | ||||
| .command("change") | ||||
| .description("Manage changes (list, create, delete)"); | ||||
|
|
||||
| change | ||||
| .command("list") | ||||
|
|
@@ -260,4 +332,52 @@ change | |||
| render(<ChangeDelete id={id} onComplete={() => process.exit(0)} />); | ||||
| }); | ||||
|
|
||||
| // Default action when no command is provided | ||||
| program.action(async () => { | ||||
| console.log("\n👋 Welcome to Superset CLI!\n"); | ||||
|
|
||||
| // Show current workspace if set | ||||
| try { | ||||
| const { getDb } = await import("./lib/db"); | ||||
| const { WorkspaceOrchestrator } = await import( | ||||
| "./lib/orchestrators/workspace-orchestrator" | ||||
| ); | ||||
| const db = getDb(); | ||||
| const orchestrator = new WorkspaceOrchestrator(db); | ||||
| const currentWorkspace = await orchestrator.getCurrent(); | ||||
|
|
||||
| if (currentWorkspace) { | ||||
| console.log( | ||||
| `📁 Current workspace: ${currentWorkspace.name || currentWorkspace.id}`, | ||||
| ); | ||||
| if ("path" in currentWorkspace && currentWorkspace.path) { | ||||
| console.log(` Path: ${currentWorkspace.path}`); | ||||
| } | ||||
| if ("branch" in currentWorkspace && currentWorkspace.branch) { | ||||
| console.log(` Branch: ${currentWorkspace.branch}`); | ||||
| } | ||||
| console.log(""); | ||||
| } else { | ||||
| console.log( | ||||
| "💡 No workspace selected. Run 'superset init' to get started!\n", | ||||
| ); | ||||
| } | ||||
| } catch (err) { | ||||
| // Silently ignore errors (e.g., no database yet) | ||||
| } | ||||
|
|
||||
| console.log("Get started with these commands:\n"); | ||||
| console.log(" superset init Create workspace (wizard)"); | ||||
| console.log(" superset dashboard Show dashboard overview"); | ||||
| console.log( | ||||
| " superset panels Show three-panel IDE interface", | ||||
| ); | ||||
| console.log(" superset workspace use <id> Switch to a workspace"); | ||||
| console.log( | ||||
| " superset agent start Start agents in current workspace", | ||||
| ); | ||||
| console.log("\nFor more information, run: superset --help\n"); | ||||
| process.exit(0); | ||||
| }); | ||||
|
|
||||
| program.parse(); | ||||
Uh oh!
There was an error while loading. Please reload this page.