diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..28a362c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,80 @@ +name: Release & Update Homebrew Formula + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + update-formula: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + + - name: Get release tag + id: tag + run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + + - name: Download source tarball and compute SHA256 + id: sha + run: | + TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${GITHUB_REF_NAME}.tar.gz" + SHA256=$(curl -sL "$TARBALL_URL" | shasum -a 256 | awk '{print $1}') + echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" + echo "url=$TARBALL_URL" >> "$GITHUB_OUTPUT" + + - name: Update formula version and SHA256 + run: | + sed -i \ + -e 's|url "https://github.com/.*/archive/refs/tags/.*\.tar\.gz"|url "${{ steps.sha.outputs.url }}"|' \ + -e 's|sha256 ".*"|sha256 "${{ steps.sha.outputs.sha256 }}"|' \ + Formula/agent-pulse.rb + + # Update only the first sha256 (the source tarball, not resource hashes) + # The sed above replaced all sha256 lines — restore the resource hashes + git checkout -- Formula/agent-pulse.rb + + # Now do a targeted update: only the url and the sha256 on the line after it + python3 - <<'PYEOF' + import re, sys + + with open("Formula/agent-pulse.rb") as f: + content = f.read() + + # Update the source url + content = re.sub( + r'( url )"https://github\.com/.*/archive/refs/tags/.*\.tar\.gz"', + rf'\1"${{ steps.sha.outputs.url }}"', + content, + count=1, + ) + + # Update the source sha256 (the one right after the url line, before license) + content = re.sub( + r'( url "https://github\.com/.*\.tar\.gz"\n )sha256 ".*?"', + rf'\g<1>sha256 "${{ steps.sha.outputs.sha256 }}"', + content, + count=1, + ) + + with open("Formula/agent-pulse.rb", "w") as f: + f.write(content) + PYEOF + + - name: Verify formula syntax + run: ruby -c Formula/agent-pulse.rb + + - name: Commit and push updated formula + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add Formula/agent-pulse.rb + git diff --cached --quiet && echo "No changes to commit" && exit 0 + git commit -m "Update Homebrew formula for ${GITHUB_REF_NAME} + + Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>" + git push origin main diff --git a/Formula/agent-pulse.rb b/Formula/agent-pulse.rb new file mode 100644 index 0000000..81b9df9 --- /dev/null +++ b/Formula/agent-pulse.rb @@ -0,0 +1,70 @@ +class AgentPulse < Formula + include Language::Python::Virtualenv + + desc "Real-time terminal dashboard for monitoring GitHub Copilot CLI sessions and agents" + homepage "https://github.com/DUBSOpenHub/copilot-cli-agent-pulse" + url "https://github.com/DUBSOpenHub/copilot-cli-agent-pulse/archive/refs/tags/v1.0.0.tar.gz" + sha256 "PLACEHOLDER" + license "MIT" + + depends_on "python@3.12" + + resource "linkify-it-py" do + url "https://files.pythonhosted.org/packages/2e/c9/06ea13676ef354f0af6169587ae292d3e2406e212876a413bf9eece4eb23/linkify_it_py-2.1.0.tar.gz" + sha256 "43360231720999c10e9328dc3691160e27a718e280673d444c38d7d3aaa3b98b" + end + + resource "markdown-it-py" do + url "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz" + sha256 "cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" + end + + resource "mdit-py-plugins" do + url "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz" + sha256 "f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6" + end + + resource "mdurl" do + url "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz" + sha256 "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + end + + resource "platformdirs" do + url "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz" + sha256 "3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a" + end + + resource "pygments" do + url "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz" + sha256 "6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f" + end + + resource "rich" do + url "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz" + sha256 "edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36" + end + + resource "textual" do + url "https://files.pythonhosted.org/packages/cf/2f/d44f0f12b3ddb1f0b88f7775652e99c6b5a43fd733badf4ce064bdbfef4a/textual-8.2.3.tar.gz" + sha256 "beea7b86b03b03558a2224f0cc35252e60ef8b0c4353b117b2f40972902d976a" + end + + resource "typing_extensions" do + url "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz" + sha256 "0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466" + end + + resource "uc-micro-py" do + url "https://files.pythonhosted.org/packages/78/67/9a363818028526e2d4579334460df777115bdec1bb77c08f9db88f6389f2/uc_micro_py-2.0.0.tar.gz" + sha256 "c53691e495c8db60e16ffc4861a35469b0ba0821fe409a8a7a0a71864d33a811" + end + + def install + virtualenv_install_with_resources + end + + test do + assert_match "Agent Pulse", shell_output("#{bin}/agent-pulse --help") + assert_match "{", shell_output("#{bin}/agent-pulse --export") + end +end diff --git a/README.md b/README.md index eb7af91..75dce19 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,20 @@ ### 🚀 Install & Launch +**Homebrew (recommended on macOS):** + +```bash +brew tap DUBSOpenHub/copilot-cli-agent-pulse +brew install agent-pulse +``` + +**Quick installer (any platform):** + ```bash curl -fsSL https://raw.githubusercontent.com/DUBSOpenHub/copilot-cli-agent-pulse/main/quickstart.sh | bash ``` -Then just type `agentpulse` — the dashboard opens in a new terminal window automatically. +Then just type `agentpulse` or `agent-pulse` to launch the dashboard. Add `--new-window` to open it in a separate window of your current terminal emulator.
@@ -73,7 +82,7 @@ alias agentpulse='~/copilot-cli-agent-pulse/start.sh' alias agentdashboard='~/copilot-cli-agent-pulse/start.sh' ``` -Then just type **`agentpulse`** or **`agentdashboard`** from anywhere — the live dashboard **automatically opens in a new terminal window** so it never blocks your current session. +Then just type **`agentpulse`** or **`agentdashboard`** from anywhere to launch the dashboard in your current terminal. Use **`--new-window`** to open it in a separate window — it auto-detects your terminal emulator (Ghostty, iTerm, Kitty, WezTerm, Alacritty, Warp, Terminal.app) and works with tmux. --- @@ -192,7 +201,7 @@ copilot-cli-agent-pulse/ ├── agent_pulse.tcss # Textual CSS stylesheet ├── pyproject.toml # Python packaging + entry point ├── requirements.txt # Python dependencies (rich, textual) -├── start.sh # Launcher (auto-opens in new terminal window) +├── start.sh # Launcher (--new-window for separate window) ├── quickstart.sh # One-command installer ├── site/ # Showcase website (GitHub Pages) │ └── index.html diff --git a/quickstart.sh b/quickstart.sh index 9088733..61c3c49 100755 --- a/quickstart.sh +++ b/quickstart.sh @@ -35,6 +35,7 @@ echo " ✅ Installed to $DEST" echo "" # Auto-add shell aliases if not already present +FISH_CONFIG="$HOME/.config/fish/config.fish" SHELL_RC="" if [ -f "$HOME/.zshrc" ]; then SHELL_RC="$HOME/.zshrc" @@ -42,18 +43,37 @@ elif [ -f "$HOME/.bashrc" ]; then SHELL_RC="$HOME/.bashrc" fi +ALIASES_ADDED=0 + +# bash/zsh aliases if [ -n "$SHELL_RC" ] && ! grep -q 'alias agentpulse=' "$SHELL_RC" 2>/dev/null; then echo "" >> "$SHELL_RC" - echo "# Agent Pulse — auto-opens live dashboard in a new terminal window" >> "$SHELL_RC" + echo "# Agent Pulse — live terminal dashboard" >> "$SHELL_RC" echo "alias agentpulse='~/copilot-cli-agent-pulse/start.sh'" >> "$SHELL_RC" echo "alias agentdashboard='~/copilot-cli-agent-pulse/start.sh'" >> "$SHELL_RC" echo " 🔗 Added 'agentpulse' and 'agentdashboard' aliases to $(basename "$SHELL_RC")" -else + ALIASES_ADDED=1 +fi + +# fish aliases +if [ -f "$FISH_CONFIG" ] || echo "$SHELL" | grep -q fish; then + mkdir -p "$(dirname "$FISH_CONFIG")" + if ! grep -q 'alias agentpulse' "$FISH_CONFIG" 2>/dev/null; then + echo "" >> "$FISH_CONFIG" + echo "# Agent Pulse — live terminal dashboard" >> "$FISH_CONFIG" + echo "alias agentpulse '~/copilot-cli-agent-pulse/start.sh'" >> "$FISH_CONFIG" + echo "alias agentdashboard '~/copilot-cli-agent-pulse/start.sh'" >> "$FISH_CONFIG" + echo " 🔗 Added 'agentpulse' and 'agentdashboard' aliases to config.fish" + ALIASES_ADDED=1 + fi +fi + +if [ "$ALIASES_ADDED" -eq 0 ]; then echo " 🔗 Aliases already configured." fi echo "" -echo " Launch it (opens in a new terminal window):" +echo " Launch it:" echo " agentpulse" echo " agentdashboard" echo "" diff --git a/start.sh b/start.sh index 2cc902f..47954ac 100755 --- a/start.sh +++ b/start.sh @@ -1,10 +1,22 @@ #!/bin/bash # Agent Pulse — Quick launcher -# Opens the live dashboard in a new terminal window (macOS) +# Runs the dashboard in the current terminal by default. +# Use --new-window to open in a new window of your current terminal emulator. SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" VENV="$SCRIPT_DIR/.venv" +# Parse --new-window flag (pass everything else through to agent_pulse.py) +NEW_WINDOW=0 +ARGS=() +for arg in "$@"; do + if [ "$arg" = "--new-window" ]; then + NEW_WINDOW=1 + else + ARGS+=("$arg") + fi +done + # Create venv if missing if [ ! -d "$VENV" ]; then echo "🐍 Creating virtual environment..." @@ -17,28 +29,114 @@ if ! "$VENV/bin/python" -c "import textual" 2>/dev/null; then "$VENV/bin/pip" install --quiet -r "$SCRIPT_DIR/requirements.txt" fi -# If already running inside a spawned terminal, just run directly -if [ "$AGENT_PULSE_SPAWNED" = "1" ]; then - exec "$VENV/bin/python" "$SCRIPT_DIR/agent_pulse.py" "$@" +# Default: run in current terminal +if [ "$NEW_WINDOW" -eq 0 ] || [ "$AGENT_PULSE_SPAWNED" = "1" ]; then + exec "$VENV/bin/python" "$SCRIPT_DIR/agent_pulse.py" "${ARGS[@]}" fi -# Open dashboard in a new terminal window -CMD="export AGENT_PULSE_SPAWNED=1; cd '$SCRIPT_DIR' && '$VENV/bin/python' '$SCRIPT_DIR/agent_pulse.py' $*" - -if command -v osascript &>/dev/null; then - # macOS — open a new Terminal.app window - osascript -e "tell application \"Terminal\" - activate - do script \"$CMD\" - end tell" &>/dev/null - echo "⚡ Agent Pulse launched in a new Terminal window." -elif command -v gnome-terminal &>/dev/null; then - gnome-terminal -- bash -c "$CMD; exec bash" &>/dev/null & - echo "⚡ Agent Pulse launched in a new terminal window." -elif command -v xterm &>/dev/null; then - xterm -e bash -c "$CMD" &>/dev/null & - echo "⚡ Agent Pulse launched in xterm." -else - # Fallback — run in current terminal - exec "$VENV/bin/python" "$SCRIPT_DIR/agent_pulse.py" "$@" +# --new-window: open in a new window/pane +CMD="export AGENT_PULSE_SPAWNED=1; cd '$SCRIPT_DIR' && '$VENV/bin/python' '$SCRIPT_DIR/agent_pulse.py' ${ARGS[*]}" + +# tmux — new window in the current session +if [ -n "$TMUX" ]; then + tmux new-window -n "AgentPulse" "bash -c '$CMD'" + echo "⚡ Agent Pulse launched in a new tmux window." + exit 0 fi + +# Detect the running terminal emulator (macOS) +TERM_APP="" +if [ "$(uname)" = "Darwin" ]; then + TERM_BUNDLE=$(__CFBundleIdentifier="" && osascript -e 'tell application "System Events" to get bundle identifier of (first process whose frontmost is true)' 2>/dev/null) + case "$TERM_BUNDLE" in + com.mitchellh.ghostty) TERM_APP="ghostty" ;; + com.googlecode.iterm2) TERM_APP="iterm" ;; + io.alacritty) TERM_APP="alacritty" ;; + net.kovidgoyal.kitty) TERM_APP="kitty" ;; + com.github.wez.wezterm) TERM_APP="wezterm" ;; + dev.warp.Warp-Stable|dev.warp*) TERM_APP="warp" ;; + com.apple.Terminal) TERM_APP="terminal" ;; + esac +fi + +case "$TERM_APP" in + ghostty) + # Ghostty — open a new window via its CLI + if command -v ghostty &>/dev/null; then + ghostty -e bash -c "$CMD" & + else + osascript -e "tell application \"Ghostty\" to activate" \ + -e "tell application \"System Events\" to keystroke \"n\" using command down" &>/dev/null + sleep 0.5 + osascript -e "tell application \"System Events\" to tell process \"Ghostty\" to keystroke \"$CMD +\"" &>/dev/null + fi + echo "⚡ Agent Pulse launched in a new Ghostty window." + ;; + iterm) + osascript -e " + tell application \"iTerm\" + activate + create window with default profile command \"bash -c '$CMD'\" + end tell" &>/dev/null + echo "⚡ Agent Pulse launched in a new iTerm window." + ;; + kitty) + kitty @ launch --type=os-window bash -c "$CMD" 2>/dev/null \ + || kitty --single-instance bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new Kitty window." + ;; + wezterm) + wezterm cli spawn --new-window -- bash -c "$CMD" 2>/dev/null \ + || wezterm start -- bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new WezTerm window." + ;; + alacritty) + alacritty -e bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new Alacritty window." + ;; + warp) + osascript -e " + tell application \"Warp\" + activate + end tell + tell application \"System Events\" to keystroke \"n\" using command down" &>/dev/null + sleep 0.5 + osascript -e "tell application \"System Events\" to keystroke \"$CMD +\"" &>/dev/null + echo "⚡ Agent Pulse launched in a new Warp window." + ;; + terminal) + osascript -e " + tell application \"Terminal\" + activate + do script \"$CMD\" + end tell" &>/dev/null + echo "⚡ Agent Pulse launched in a new Terminal window." + ;; + *) + # Linux / fallback detection + if command -v ghostty &>/dev/null; then + ghostty -e bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new Ghostty window." + elif command -v kitty &>/dev/null; then + kitty bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new Kitty window." + elif command -v wezterm &>/dev/null; then + wezterm start -- bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new WezTerm window." + elif command -v alacritty &>/dev/null; then + alacritty -e bash -c "$CMD" & + echo "⚡ Agent Pulse launched in a new Alacritty window." + elif command -v gnome-terminal &>/dev/null; then + gnome-terminal -- bash -c "$CMD; exec bash" & + echo "⚡ Agent Pulse launched in a new terminal window." + elif command -v xterm &>/dev/null; then + xterm -e bash -c "$CMD" & + echo "⚡ Agent Pulse launched in xterm." + else + echo "⚠️ Could not detect terminal emulator — running in current terminal." + exec "$VENV/bin/python" "$SCRIPT_DIR/agent_pulse.py" "${ARGS[@]}" + fi + ;; +esac