TL; DR
- Gemini CLIで共和暦の時計を作成
はじめに
今週突如として現れたGemini CLI。ソースコードがOSS公開されており、なにより無料で使えます(2025/06/29現在)。
というわけで、Claude Codeもまだ使いこなせていないのにホイホイつられて 流行りに乗って触ってみました。
腕試しということで、↓の条件に合う小さなツールがよさそうです。
- Gemini CLIのサンドボックスでデフォルトで使える技術スタック(=Node.js)
- 学習データに含まれていなさそうな
微妙に役に立たない題材
そこで今回は、共和暦のカレンダーと時計を表示するWebアプリをVibe Codingで作成して(作成させて?)みました。
共和暦についておさらい
共和暦はフランス革命の際に作られた暦です。「テルミドールのクーデター」の「テルミドール」は共和暦の11番目の月です。
この暦の特徴として、時間に10進法を持ち込んだ点が挙げられます。
1日 | 10時間 |
1時間 | 100分 |
1分 | 100秒 |
メートル法等と異なり10年ほどで廃止されてしまいましたが、本記事ではこの暦をオンライン上に再現したいと思います。
作ったもの
アナログ時計とカレンダーです。1(共和暦)秒ごとに針が動きます。
うるう秒等の考慮はできていないので、あくまでジョークアプリとしてご利用ください。
実装
肝となるアナログ時計の実装は以下の部分です。
// ※オリジナルのコメント(Geminiが作成)は英語だったので、著者が日本語に翻訳
const now = new Date();
// Calculate total seconds from midnight in Gregorian time, including milliseconds for smoother movement
const gregorianSecondsToday = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1000;
// 日数に変換したのち、共和暦の時間単位に変換
const dayFraction = gregorianSecondsToday / 86400;
const republicanHours = dayFraction * 10;
const republicanMinutes = (republicanHours * 100) % 100;
const republicanSeconds = Math.floor((republicanMinutes * 100) % 100);
// 針(hand)の角度を計算
// 時針: 10時間で 2*PI 回転
const hourAngle = (republicanHours * (Math.PI / 5)) - (Math.PI / 2);
// 分針: 100分で 2*PI 回転
const minuteAngle = (republicanMinutes * (Math.PI / 50)) - (Math.PI / 2);
// 秒針: 100秒で 2*PI 回転
const secondAngle = (republicanSeconds * (Math.PI / 50)) - (Math.PI / 2);
00:00から経過したグレゴリオ暦(=普段私たちが使っている暦)での秒数を共和暦の経過秒数に変換し、再度時、分、秒に分割しています。
針の角度は弧度法で指定しています。
方向については、canvasの座標はy軸が上限反転しているため、値を増やすことで時計回りに進みます。
最後に、00:00のときは真上1に針があるので角度から $- \frac{\pi}{2}$ を引きます。
上記の処理が setTimeout
で1(共和暦)秒ごとに呼び出されることで、時計の針が動いていきます。
setInterval(() => {
updateCalendar();
drawClock();
}, 864); // 1日 = 86400(グレゴリオ暦)秒 = 100000共和暦秒なので、1共和暦秒 = 0.864(グレゴリオ暦)秒
Vibe Codingでの開発
Gemini CLIの開発環境
Gemini CLIには、安全に開発を行うためのサンドボックスモードが備わっています。
$ gemini -h
...
-s, --sandbox Run in sandbox? [boolean]
--sandbox-image Sandbox image URI. [string]
...
サンドボックスを有効にすると、Gemini CLIはサンドボックスのDockerコンテナの中のみで作業を行います。誤って作業ディレクトリ外の必要なファイルを消してしまう心配はありません。Vibe Codingで確認なしでコマンドを実行させる際には使ったほうが安全です。
また、サンドボックス環境のDockerコンテナには、Gemini CLIを動かすためのNode.jsがプリインストールされています。そのため、Nodeで開発を行う場合はインストール等不要で開発を始められます2。
$ docker run -it --rm us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.1.5 bash
node@c6fa9ea6dac9:/$ node -v
v20.19.3
node@c6fa9ea6dac9:/$ npm -v
10.8.2
ただし、ネットワークをコンテナ外とつないでいないため、npm run dev
によるアプリ起動はずっとハングした状態になります。いったん ESCでコマンドを止めて、コンテナ外で手動で実行しました。
Gemini CLIとのやり取り
最後に、開発風景としてGemini CLIとのやり取りを紹介します。
一度も具体的な実装方針については言及していませんが、不具合報告だけで要件をくみ取って実装を進めることができました。
プロンプト(1回目)
viteを使用して、ブラウザ上に共和歴のアナログ時計を描画するwebサイトを構築してください。使用する技術は以下の通りです。
- TypeScript
- Vite
仕様
- 時計はアナログ
- カレンダーで日付も表示
共和暦の計算方法は一切説明しなかったのですが、自前で設計を考えほぼ完成系のコードが出力されました。正直時計の上側が 12
になったり一日を86400共和暦秒で計算したりすると思っていたので驚きです(驚き屋ノルマ達成)。
ただし、更新のタイミングが1(グレゴリオ暦)秒ごとで秒針が中途半端な位置に描画されていました。
const decimalTime = (hours * 3600 + minutes * 60 + seconds) / 8640;
const hourAngle = (decimalTime * 10) * (Math.PI / 5) - Math.PI / 2;
const minuteAngle = ((decimalTime * 1000) % 100) * (Math.PI / 50) - Math.PI / 2;
const secondAngle = ((decimalTime * 100000) % 100) * (Math.PI / 50) - Math.PI / 2;
setInterval(() => {
updateCalendar();
drawClock();
}, 1000);
プロンプト(2回目)
グレゴリオ暦の1秒ではなく共和暦の1秒ごとに針が動くようにしてください。
冒頭の実装通り、共和暦秒ごとに更新する実装に修正されました。一方、1秒以下の端数が角度に反映されて秒針の位置がずれてしまいました。
プロンプト(3回目)
秒は切り捨てにしてください。(時、分はそのままにしてください)
秒針がちょうどの位置に描かれるようになりました。厳密には1秒以下の遅れが発生していますが許容範囲とします3。
- const republicanSeconds = (republicanMinutes * 100) % 100;
+ const republicanSeconds = Math.floor((republicanMinutes * 100) % 100);
想定する実装になったので、ここでGemini CLIを終了しました。
途中で寝落ちしたので経過時間が凄いことになっていますが、確認込みで実質15分くらいしか作業していません。
> /quit
╭─────────────────────────────────────╮
│ │
│ Agent powering down. Goodbye! │
│ │
│ │
│ Cumulative Stats (4 Turns) │
│ │
│ Input Tokens 288,427 │
│ Output Tokens 6,197 │
│ Thoughts Tokens 23,866 │
│ ───────────────────────────────── │
│ Total Tokens 318,490 │
│ │
│ Total duration (API) 4m 28s │
│ Total duration (wall) 12h 1m 20s │
│ │
╰─────────────────────────────────────╯
おわりに
以上、Vibe Codingで共和暦の時計を実装してみた記事でした。
正直私は「コードが書きたいから書く」タイプのプログラマなのでVibe Codingを敬遠していたのですが、簡単なツールであればほぼ丸投げができることが分かりました。そして、ニッチな題材であっても設計に詰まることは無かったので、新しいアイデアに対しても使えそうです。
あとは自分でやりたい欲求を以下に抑えるかですね...