0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エンジニアのための最強ポモドーロタイマーをSketchyBarに実装してみた

Last updated at Posted at 2025-04-04

はじめに

最近は学習や仕事の経過を、
スマートに、しかも素晴らしく表示したいと思い、

SketchyBarでポモドーロ機能(Pomodoro Timer)を追加してみました!

なぜ作ったのか?

ポモドーロ管理用にスマホアプリやタイマーアプリを使うことも多いですが、
実際にはスマホに触れた瞬間に通知やメッセージ、SNSを開いてしまい、
集中が途切れてしまうことがよくありました。

エンジニアとして、常にPCの上部(メニューバー)にポモドーロタイマーが常駐しているほうが、
作業フローを壊さず、理想的だと考えました。

この問題意識から、SketchyBar上にポモドーロタイマーを常設することを目指して今回作りました!

SketchyBarって何?

SketchyBarは、macOSのメニューバーを自由にカスタマイズできるツールです。
アイコンやラベルを設定したり、スクリプト管理や消費表示も自由。

こんな感じ!

image.png

必要なもの

今回の実装には以下が必要です:

  • SketchyBar(本体)
  • jq(SketchyBarの状態取得に使用)
  • terminal-notifier(タイマー終了時の通知を飛ばすため)

terminal-notifierはHomebrewでインストールできます。

brew install terminal-notifier

作った機能

image.png
image.png

1. Pomodoro Timer

  • メニューバーの **中央(Center)**に
    • 【トマト(WORK)】
    • 【コーヒー(BREAK)】
      のボタンを表示
  • クリックするとタイマーカウントを開始
  • macOSの通知(terminal-notifier)も飛ぶ!

2. Pomodoro History

  • 今日のポモドーロ成果をメニューバーの **左端(Left)**に表示
  • 例: 🍅🍅☕️🍅(とか)
  • クリックするとその場でリフレッシュ

実装コード

ファイル構成はこんな感じ

📂 items/pomodoro_work.sh

#!/bin/bash
sketchybar --add item work_button center \
           --set work_button label="🍅" \
                 drawing=off \
                 click_script="NAME=work_button $PLUGIN_DIR/pomodoro.sh"

📂 items/pomodoro_break.sh

#!/bin/bash
sketchybar --add item break_button center \
           --set break_button label="☕️" \
                 drawing=off \
                 click_script="NAME=break_button $PLUGIN_DIR/pomodoro.sh"

📂 items/pomodoro.sh

sketchybar --add item pomodoro_launcher right \
           --set pomodoro_launcher \
                 icon="􀖈" \
                 icon.color=$YELLOW \
                 padding_left=0 \
                 padding_right=-5 \
                 click_script="$PLUGIN_DIR/pomodoro_launcher.sh"

📂 items/pomodoro_history.sh

#!/bin/bash
source "$HOME/.config/sketchybar/colors.sh"

POMO_HISTORY="$HOME/.config/sketchybar/pomodoro/.pomodoro_history"
today=$(date '+%Y-%m-%d')

output=""

if [ -f "$POMO_HISTORY" ]; then
    while IFS= read -r line || [ -n "$line" ]; do
        if [[ "$line" == "$today"* ]]; then
            if [[ "$line" == *"[WORK]"* ]]; then
                output+="🍅"
            elif [[ "$line" == *"[REST]"* ]]; then
                output+="☕️"
            fi
        fi
    done < "$POMO_HISTORY"
fi

if [ -z "$output" ]; then
    output="No Pomo"
fi

sketchybar --set pomo_history label="$output" label.color="$YELLOW"

📂 plugins/pomodoro.sh

#!/bin/bash
source "$HOME/.config/sketchybar/colors.sh"

WORK_MIN=50
BREAK_MIN=10

POMO_DIR="$HOME/.config/sketchybar/pomodoro"
MODE_FILE="$POMO_DIR/pomo_mode"
PID_FILE="$POMO_DIR/pomo_timer.pid"
HISTORY_FILE="$POMO_DIR/.pomodoro_history"

mkdir -p "$POMO_DIR"

BUTTON_WORK="work_button"
BUTTON_BREAK="break_button"

start_timer() {
    local duration="$1"
    local button="$2"
    local label="$3"

    local START_TIME=$(date '+%Y-%m-%d %H:%M:%S')

    (
      TIME_LEFT=$((duration * 60))
      while [ $TIME_LEFT -ge 0 ]; do
          MINUTES=$((TIME_LEFT / 60))
          SECONDS=$((TIME_LEFT % 60))
          TIME_STR=$(printf "%02d:%02d" $MINUTES $SECONDS)
          sketchybar --set "$button" label="$label $TIME_STR" label.color=$YELLOW drawing=on 
          sleep 1
          TIME_LEFT=$((TIME_LEFT - 1))
      done

      local END_TIME=$(date '+%Y-%m-%d %H:%M:%S')  # Save end time now

      # Send macOS notification after timer ends
      if [ "$label" = "🍅" ]; then
          terminal-notifier \
            -title 'Pomodoro'\
			-message 'Work Timer is up! Take a Break 🍅'\
			-appIcon "$HOME/.config/sketchybar/img/pomodoro.png"\
			-sound Funk
          echo "$START_TIME  $END_TIME  [WORK]  $WORK_MIN mins" >> "$HISTORY_FILE"
      elif [ "$label" = "☕️" ]; then
          terminal-notifier \
            -title 'Pomodoro'\
            -message 'Break is over! Get back to work ☕️'\
			-appIcon "$HOME/.config/sketchybar/img/pomodoro.png"\
			-sound Funk
          echo "$START_TIME  $END_TIME  [REST]  $BREAK_MIN mins" >> "$HISTORY_FILE"

      fi
      # Clean up PID file after timer naturally ends
      rm -f "$PID_FILE"

      # Reset UI after timer completion
      sketchybar --set $BUTTON_WORK label="🍅" drawing=on \
                 --set $BUTTON_BREAK label="☕️" drawing=on
      echo "none" > "$MODE_FILE"
    ) &
    echo $! > "$PID_FILE"
}

stop_timer() {
    # Stop and clean up timer process
    if [ -f "$PID_FILE" ]; then
        kill $(cat "$PID_FILE") 2>/dev/null
        rm -f "$PID_FILE"
    fi
    echo "none" > "$MODE_FILE"
    sketchybar --set $BUTTON_WORK label="🍅" drawing=on \
               --set $BUTTON_BREAK label="☕️" drawing=on
}

case "$NAME" in
  "work_button")
    current_mode=$(cat "$MODE_FILE" 2>/dev/null)
    if [ "$current_mode" = "work" ]; then
        stop_timer
    else
        stop_timer
        echo "work" > "$MODE_FILE"
        # 片方オだけオフにすると一度アイコンが真ん中に移動し、start_timerでアイコンの位置が変わりチラつく
        # そのチラつきへの対策で、一度全てオフにすることでチラつきを減らしている。
        sketchybar --set $BUTTON_WORK drawing=off \
                   --set $BUTTON_BREAK drawing=off
        start_timer $WORK_MIN "$BUTTON_WORK" "🍅"
    fi
    ;;
  "break_button")
    current_mode=$(cat "$MODE_FILE" 2>/dev/null)
    if [ "$current_mode" = "break" ]; then
        stop_timer
    else
        stop_timer
        echo "break" > "$MODE_FILE"
        # 片方オだけオフにすると一度アイコンが真ん中に移動し、start_timerでアイコンの位置が変わりチラつく
        # そのチラつきへの対策で、一度全てオフにすることでチラつきを減らしている。
        sketchybar --set $BUTTON_WORK drawing=off \
                   --set $BUTTON_BREAK drawing=off
        start_timer $BREAK_MIN "$BUTTON_BREAK" "☕️"
    fi
    ;;
  *)
    ;;
esac

📂 plugins/pomodoro_launcher.sh

#!/bin/sh

pomo_on() {
  sketchybar --set work_button drawing=on \
             --set break_button drawing=on \
             --set pomo_history drawing=on
}

pomo_off() {
  sketchybar --set work_button drawing=off \
             --set break_button drawing=off \
             --set pomo_history drawing=off
}

if [ "$1" = "on" ]; then
  pomo_on
elif [ "$1" = "off" ]; then
  pomo_off
else
  if [ "$(sketchybar --query work_button | jq -r '.geometry.drawing')" = "on" ]; then
    pomo_off
  else
    pomo_on
  fi
fi

まとめ

  • SketchyBarを使うと、自分の効率をスマートに経過できる
  • Pomodoro Timerも、成果表示もすぐ実装できる
  • 今までのポモドーロの履歴も.pomodoro_historyに記録できる
2025-04-04 11:41:47  2025-04-04 12:31:47  [WORK]  50 mins
2025-04-04 12:41:47  2025-04-04 12:51:47  [REST]  10 mins
2025-04-04 13:11:47  2025-04-04 14:01:47  [WORK]  50 mins
2025-04-04 14:11:47  2025-04-04 15:01:47  [WORK]  50 mins
2025-04-04 15:11:47  2025-04-04 16:01:47  [WORK]  50 mins
2025-04-04 16:11:47  2025-04-04 17:01:47  [WORK]  50 mins
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?