Skip to content

Commit 1bb472a

Browse files
thestack_aiclaude
andcommitted
feat: v0.2.0 — CLI command + proper icon + installer progress bar
1. jarvis-orb CLI: one command starts Brain + opens Orb - jarvis-orb (full), --brain (brain only), --orb (orb only), --demo - Registered in PATH on both macOS and Windows 2. App icon: cyan/purple gradient orb with glow (replaces placeholder) - PNG 32/128/256 + ICO for Windows 3. Installer UI: progress bar [████░░░░] 2/4 at each step - Both macOS (bash) and Windows (PowerShell) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d1b2111 commit 1bb472a

8 files changed

Lines changed: 199 additions & 5 deletions

File tree

brain/jarvis_brain/cli.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""Jarvis Orb — CLI entry point.
2+
3+
Usage:
4+
jarvis-orb Start Brain + open Orb
5+
jarvis-orb --brain Start Brain only (WebSocket server)
6+
jarvis-orb --orb Open Orb only
7+
jarvis-orb --demo Start demo mode (fake events)
8+
"""
9+
10+
import argparse
11+
import asyncio
12+
import os
13+
import platform
14+
import subprocess
15+
import sys
16+
import time
17+
18+
19+
def find_orb_app():
20+
"""Find the Orb app on disk."""
21+
system = platform.system()
22+
if system == "Darwin":
23+
paths = [
24+
"/Applications/Jarvis Orb.app",
25+
os.path.expanduser("~/Applications/Jarvis Orb.app"),
26+
]
27+
for p in paths:
28+
if os.path.exists(p):
29+
return p
30+
elif system == "Windows":
31+
# Common install locations
32+
appdata = os.environ.get("LOCALAPPDATA", "")
33+
paths = [
34+
os.path.join(appdata, "Jarvis Orb", "Jarvis Orb.exe"),
35+
os.path.join(os.environ.get("PROGRAMFILES", ""), "Jarvis Orb", "Jarvis Orb.exe"),
36+
]
37+
for p in paths:
38+
if os.path.exists(p):
39+
return p
40+
return None
41+
42+
43+
def start_brain(demo=False):
44+
"""Start Brain Lite WebSocket server in background."""
45+
brain_dir = os.path.expanduser("~/.jarvis-orb")
46+
lib_dir = os.path.join(brain_dir, "lib")
47+
sep = ";" if platform.system() == "Windows" else ":"
48+
pythonpath = f"{lib_dir}{sep}{brain_dir}"
49+
50+
module = "jarvis_brain.demo_server" if demo else "jarvis_brain.demo_server"
51+
python = "python" if platform.system() == "Windows" else "python3"
52+
53+
env = os.environ.copy()
54+
env["PYTHONPATH"] = pythonpath
55+
56+
proc = subprocess.Popen(
57+
[python, "-m", module],
58+
cwd=brain_dir,
59+
env=env,
60+
stdout=subprocess.DEVNULL,
61+
stderr=subprocess.DEVNULL,
62+
)
63+
return proc
64+
65+
66+
def open_orb():
67+
"""Open the Orb desktop app."""
68+
app_path = find_orb_app()
69+
if not app_path:
70+
print(" Orb app not found. Install it first.")
71+
return None
72+
73+
system = platform.system()
74+
if system == "Darwin":
75+
subprocess.Popen(["open", app_path])
76+
elif system == "Windows":
77+
subprocess.Popen([app_path])
78+
return app_path
79+
80+
81+
def main():
82+
parser = argparse.ArgumentParser(
83+
description="Jarvis Orb — AI Brain + Realtime Visualizer"
84+
)
85+
parser.add_argument("--brain", action="store_true", help="Start Brain only")
86+
parser.add_argument("--orb", action="store_true", help="Open Orb only")
87+
parser.add_argument("--demo", action="store_true", help="Demo mode (fake events)")
88+
args = parser.parse_args()
89+
90+
print()
91+
print(" \033[36m\033[1mJARVIS ORB\033[0m")
92+
print()
93+
94+
if args.brain or (not args.orb):
95+
mode = "demo" if args.demo else "brain"
96+
print(f" \033[32m✓\033[0m Brain starting...")
97+
brain_proc = start_brain(demo=args.demo)
98+
time.sleep(1)
99+
if brain_proc.poll() is None:
100+
print(f" \033[32m✓\033[0m Brain running (PID {brain_proc.pid})")
101+
else:
102+
print(f" \033[31m✗\033[0m Brain failed to start")
103+
return
104+
105+
if args.orb or (not args.brain):
106+
print(f" \033[32m✓\033[0m Opening Orb...")
107+
path = open_orb()
108+
if path:
109+
print(f" \033[32m✓\033[0m Orb launched")
110+
111+
print()
112+
print(" \033[36mYour AI is thinking.\033[0m")
113+
print(" \033[2mPress Ctrl+C to stop.\033[0m")
114+
print()
115+
116+
try:
117+
while True:
118+
time.sleep(1)
119+
except KeyboardInterrupt:
120+
print("\n Stopped.")
121+
122+
123+
if __name__ == "__main__":
124+
main()

install.ps1

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,22 @@ $BrainDir = "$env:USERPROFILE\.jarvis-orb"
88
$BrainBin = "$BrainDir\bin"
99

1010
# ── Colors ──
11+
$Script:StepNum = 0
12+
$Script:TotalSteps = 4
13+
1114
function Write-Cyan($msg) { Write-Host " $msg" -ForegroundColor Cyan }
1215
function Write-Ok($msg) { Write-Host "$msg" -ForegroundColor Green }
1316
function Write-Warn($msg) { Write-Host " ! $msg" -ForegroundColor Yellow }
1417
function Write-Info($msg) { Write-Host " $msg" -ForegroundColor DarkGray }
15-
function Write-Step($msg) { Write-Host "`n$msg" -ForegroundColor White }
18+
function Write-Step($msg) {
19+
$Script:StepNum++
20+
$filled = [int]($Script:StepNum * 20 / $Script:TotalSteps)
21+
$empty = 20 - $filled
22+
$bar = ("" * $filled) + ("" * $empty)
23+
Write-Host ""
24+
Write-Host " [$bar] $($Script:StepNum)/$($Script:TotalSteps)" -ForegroundColor DarkGray
25+
Write-Host "$msg" -ForegroundColor White
26+
}
1627

1728
# ── Header ──
1829
Write-Host ""
@@ -69,13 +80,27 @@ try {
6980
}
7081

7182
# Create launcher
72-
$launcherContent = @"
83+
$brainLauncher = @"
7384
@echo off
7485
set PYTHONPATH=$BrainDir\lib;$BrainDir
7586
python -m jarvis_brain.mcp_server %*
7687
"@
77-
Set-Content -Path "$BrainBin\jarvis-brain.bat" -Value $launcherContent
78-
Write-Ok "Brain launcher → $BrainBin\jarvis-brain.bat"
88+
Set-Content -Path "$BrainBin\jarvis-brain.bat" -Value $brainLauncher
89+
90+
$orbLauncher = @"
91+
@echo off
92+
set PYTHONPATH=$BrainDir\lib;$BrainDir
93+
python -m jarvis_brain.cli %*
94+
"@
95+
Set-Content -Path "$BrainBin\jarvis-orb.bat" -Value $orbLauncher
96+
Write-Ok "Commands → jarvis-orb, jarvis-brain"
97+
98+
# Add to PATH
99+
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
100+
if ($currentPath -notlike "*$BrainBin*") {
101+
[Environment]::SetEnvironmentVariable("Path", "$BrainBin;$currentPath", "User")
102+
Write-Ok "Added to PATH (restart terminal to use)"
103+
}
79104

80105
# ── Step 3: Claude Code MCP ──
81106
Write-Step "Configuring Claude Code"

install.sh

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,19 @@ case "$OS" in
3939
*) echo -e " ${RED}Unsupported: $OS${R}"; exit 1 ;;
4040
esac
4141

42+
STEP_NUM=0
43+
TOTAL_STEPS=4
44+
4245
step() {
46+
STEP_NUM=$((STEP_NUM + 1))
4347
echo ""
48+
# Progress bar
49+
local filled=$((STEP_NUM * 20 / TOTAL_STEPS))
50+
local empty=$((20 - filled))
51+
local bar=""
52+
for i in $(seq 1 $filled); do bar="${bar}"; done
53+
for i in $(seq 1 $empty); do bar="${bar}"; done
54+
echo -e " ${DIM}[${bar}] ${STEP_NUM}/${TOTAL_STEPS}${R}"
4455
echo -e " ${CYAN}${R} ${B}$1${R}"
4556
}
4657

@@ -60,6 +71,19 @@ fail() {
6071
echo -e " ${RED}${R} $1"
6172
}
6273

74+
spinner() {
75+
local pid=$1
76+
local msg=$2
77+
local chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
78+
local i=0
79+
while kill -0 $pid 2>/dev/null; do
80+
printf "\r ${CYAN}${chars:$i:1}${R} ${DIM}${msg}${R}" >&2
81+
i=$(( (i + 1) % ${#chars} ))
82+
sleep 0.1
83+
done
84+
printf "\r \r" >&2
85+
}
86+
6387
# ── Step 1: Environment ──
6488
step "Checking environment"
6589
info "$OS $ARCH"
@@ -107,7 +131,28 @@ export PYTHONPATH="$HOME/.jarvis-orb/lib:$HOME/.jarvis-orb"
107131
exec python3 -m jarvis_brain.mcp_server "$@"
108132
EOF
109133
chmod +x "$BRAIN_BIN/jarvis-brain"
110-
ok "Brain launcher → ~/.jarvis-orb/bin/jarvis-brain"
134+
135+
cat > "$BRAIN_BIN/jarvis-orb" << 'EOF'
136+
#!/bin/bash
137+
export PYTHONPATH="$HOME/.jarvis-orb/lib:$HOME/.jarvis-orb"
138+
exec python3 -m jarvis_brain.cli "$@"
139+
EOF
140+
chmod +x "$BRAIN_BIN/jarvis-orb"
141+
ok "Commands → jarvis-orb, jarvis-brain"
142+
143+
# Add to PATH if not already
144+
if [[ ":$PATH:" != *":$BRAIN_BIN:"* ]]; then
145+
SHELL_RC=""
146+
if [ -f "$HOME/.zshrc" ]; then SHELL_RC="$HOME/.zshrc"
147+
elif [ -f "$HOME/.bashrc" ]; then SHELL_RC="$HOME/.bashrc"
148+
fi
149+
if [ -n "$SHELL_RC" ]; then
150+
if ! grep -q "jarvis-orb/bin" "$SHELL_RC" 2>/dev/null; then
151+
echo 'export PATH="$HOME/.jarvis-orb/bin:$PATH"' >> "$SHELL_RC"
152+
ok "Added to PATH in $(basename $SHELL_RC)"
153+
fi
154+
fi
155+
fi
111156

112157
# ── Step 3: Claude Code MCP ──
113158
step "Configuring Claude Code"

orb/src-tauri/icons/128x128.png

18.9 KB
Loading

orb/src-tauri/icons/128x128@2x.png

63.8 KB
Loading

orb/src-tauri/icons/256x256.png

63.8 KB
Loading

orb/src-tauri/icons/32x32.png

1.21 KB
Loading

orb/src-tauri/icons/icon.ico

1.21 KB
Binary file not shown.

0 commit comments

Comments
 (0)