常駐や業務委託で働いていると月末に「今月の稼働表を出してください」というのが来ます。
先月の自分が何時に働き始めて何時まで作業していたかを思い出しながら30日分埋める作業で、しかも請求に直結するので適当には書けません。
毎月やっているのに毎月面倒なので、すでにどこかに残っている記録から作れないか試してみました。結論から言うと作れたのですが、最初のやり方は完全に間違っていました。
発想
タイマーを押したり常駐ソフトを入れたりしなくても、働いていれば下記の様な記録は残っています。
- Slackに投稿した時刻
- GitHubにコミットした時刻
- チケットを更新した時刻
- ドキュメントを編集した時刻
これらはすでにAPIで取れますし、過去に遡れます。先月分を今から作るということができるのがタイマー式のツールとの決定的な違いだと思います。
そこで活動の時刻を集めて、塊ごとに開始・終了・休憩を推定する形にしてみました。
コミット履歴だけで作った場合
まずGitHubだけで試してみました。自分の1か月分のコミットを取って稼働表にした結果が下記です。
| 稼働した日 | 13日 |
| 活動イベント | 43件 |
| 推定の実働 | 9時間01分 |
1か月で9時間はさすがにそんなわけがないのですが、理由は考えれば当たり前でコミットは成果物であって作業時間ではないからです。
- 3時間実装してコミットは1回
- 調査していた時間はコミットにならない
- レビュー、打ち合わせ、環境構築、障害対応、どれも残らない
- そもそも毎日コミットするとは限らない
エンジニアの仕事はコードを書くだけではないのでコミット履歴は稼働の一部しか写しません。GitHubさえ繋げば稼働表ができる、というのは成立しませんでした。
深夜作業の扱い
次にSlackを足しました。チャットは業務時間中ずっと発生するので密度が段違いです。
ところが今度は別の問題が出ました。深夜1時まで作業した日の稼働表が下記の様になります。
2026-06-17 09:12 - 23:58 実働 13:202026-06-18 00:15 - 01:03 実働 0:48 休憩 14:00 ← ???日付をまたいだ瞬間に別の日として切られ、しかも「00:15から01:03まで働いてそのあと14時間休憩した」という珍妙な行ができます。
暦日で切っていたのが原因でした。人間の感覚では深夜1時の作業は前日の続きなので、稼働日の始まりを5:00にしました。5時より前の活動は前日に属する扱いです。これで深夜作業が1行にまとまります。
調整したところ
1. ソースごとに前後の重みを変える
活動時刻は点ですが稼働は線です。点の前後をどれだけ稼働とみなすかを決める必要があり、ここをソースごとに変えました。
| ソース | 前 | 後 |
|---|---|---|
| Slack | 0.5 | 0.5 |
| GitHub | 3.0 | 0.5 |
| チケット系 | 1.0 | 0.5 |
コミットの前には作業時間があります。チャットの返信は書いた瞬間が作業ですが、コミットは3時間書いた結果なので前側を厚く取らないと実態に合いません。
倍率が妥当かは実データで確認しました。自分の6月のデータでGitHubの前バッファを0.5から3.0に上げたときの増分が下記です。
| 実働の増加 | +8時間01分(+6.1%) |
| 理論上の最大増加に対する割合 | 25% |
75%はすでにSlackのセッションに含まれていました。つまり大半のコミットはチャットもしている時間帯に打たれていて二重計上にはなっておらず、増えた8時間はコミットしかしていない時間帯、要するに集中して書いていた時間です。
2. 休憩の判定は45分
活動の空白がどれだけ続いたら休憩とみなすか。ここは45分にしました。
労働基準法では労働時間が6時間を超えると45分以上、8時間を超えると1時間以上の休憩が要ります。45分は法定の最小単位なのでここを閾値にすると、法的に休憩とみなせる長さの空白が休憩になります。30分だと打ち合わせの移動や離席まで休憩にされ、実働が不当に短く出ました。
3. 何をしていたかは見出しだけ取る
常駐先の稼働表には時間の隣に作業内容の欄があることが多いのでここも埋めたいのですが、取るものは厳密に絞りました。
| 取る | 取らない |
|---|---|
| コミットメッセージ | Slackのメッセージ本文 |
| チケットの件名 | チケットのコメント本文 |
| Slackのチャンネル名 | |
| ドキュメントのファイル名 |
見出しは本人が自分の作業を説明するために書いたものですが、本文は他人との会話です。ここを越えると稼働表を作る道具から監視ツールに変わってしまうと思います。
粒度も調整しました。最初はコミットメッセージを1行ずつ出していたのですが、12回コミットした日に12行並んでも結局まとめ直すことになります。稼働表に書くのはどの案件をやったかなので、既定はリポジトリ名・プロジェクト名・チャンネル名にしました。
金額に関して
残業の内訳(所定内・法定内残業・法定時間外・深夜・法定休日)は出します。ここは時間の分類なので活動ログから機械的に決まります。
ただし割増率と金額は出しません。そこから先は労務の判断だからです。固定残業の扱い、休日の定義、単価の解釈は契約ごとに違います。推定値に金額を掛けた瞬間にこれで請求していいのかという判断を機械がしたことになるので、時間の内訳までを出して金額は人が決める、という線を引きました。
作ったもの
そういう形で作ったのがこれです。
Slack / GitHub / GitLab / Backlog / Jira / OpenProject / Redmine / Googleドライブの活動時刻から日別の開始・終了・休憩・実働を推定して稼働表の下書きを出します。CSVとスプレッドシート貼り付け用の出力まで含みます。
- PCに常駐ソフトを入れない。客先常駐だと監視エージェントを入れられない現場が多いので、サーバー側のAPIログだけを読む形にしています
- 事前の準備なしで過去に遡れる。記録を取り始めていなくても、すでに残っているログから先月分を再構成できます
今月と先月分は無料で作れます。
まとめ
やってみて一番の収穫は「コミットだけでは月9時間にしかならない」を数字で見たことでした。
作る前はエンジニアなんだからGitHubを繋げば十分だろうと思っていたのですが、実際にやるとそれはコードを書いている時間しか仕事とみなさないという前提でした。調査も打ち合わせもレビューも稼働です。
稼働表を自動で作るというのは何を稼働とみなすかを決める作業で、そこを外すと動いてはいるが数字が使い物にならないものができあがります。同じことをやろうとしている方の参考になれば幸いです。