Compare commits

..

No commits in common. "master" and "advent-22" have entirely different histories.

34 changed files with 0 additions and 1187 deletions

View File

@ -1,127 +0,0 @@
---
author: usbharu
draft: false
categories:
- null
date: 2025-12-03T15:29:46+09:00
tags:
- null
keywords:
- null
title: Misskeyサーバー1周年を振り返って
relpermalink: posts/2025-12-03/
url: posts/2025-12-03/
decription: Misskeyサーバー1周年を振り返って
---
{{< alert icon="circle-info" >}}
この記事は [しょぼねこ Advent Calendar 2025](https://adventar.org/calendars/12131) 23 日目の記事です。
{{< /alert >}}
blog.usbharu.devへようこそ 昨日に引き続きありきたりなやつです。
12/29で1周年を迎える招待制身内用Misskeyサーバーがあります。このサーバーは2代目で、先代サーバーは物理サーバーの管理者といろいろあって閉鎖されたところをusbharuが新しく建てたという感じです。僕は物理サーバーの管理者としてサーバーの管理をしていますが、Misskeyサーバーの運営としてはほとんど関わっていません。そんなちょっと特殊なサーバーですが、幸い今のところ大きな人間関係トラブルなどはなく運用できていると思います。
## 1周年時点でのいろんなデータ
住人に許可も取らず身内ネタをアドベントカレンダー記事にべらべらと書くのもアレなので、大体の数字を見て振り返って見ましょう。なお執筆時点でのデータなので正確に1年経過した時点でのデータではありません。
| 種類 | 数値 |
| ------------------------------ | ------------ |
| ユーザー数 | 24アカウント |
| ノート数 | 45420 |
| 認知サーバー数 | 約1500 |
| Pubサーバー数 | 約90 |
| Subサーバー数 | 約90 |
| カスタム絵文字数 | 約90 |
| メディア数 | 約7000 |
| メディアサイズ | 約2GB |
| 最新のバックアップデータサイズ | 約250MB |
### ユーザー数とノート数
未ログイン状態でも見れるデータなので正確な数値を書いています。システムアカウントとかを含めての数値ですが、思っていたより多いですね。アクティブユーザーが多いのも納得です。
ノート数はサーバーで投稿されたもので、連合先の投稿は含んでいません。
PrometheusとGrafanaを使った長期間の推移データもあるんですが、停電でおうちシステムが壊滅してから復旧してないので見れません。残念
### 認知サーバー数とPub/Subサーバー数
認知サーバー数はリレーとかに入っていない招待制サーバーな割には多い方なんじゃないでしょうか。
Pub/Subサーバー数というのはフォロワー/フォロイーのサーバーが何種類かということです。これは意外と少ないほうかも知れません。
### カスタム絵文字数とメディア数/サイズ
これは物理サーバーの管理人しか見れませんね。7000というのはサムネイルも含みますので、実際に投稿されている画像などは半分ほどになります。僕の個人サーバー(misskey.usbharu.dev)と比べて相当多いので、画像などの投稿が活発なんじゃないでしょうか。
サイズは約2GBということで、やはり動画などより画像が多いと思われます。
### 最新のバックアップデータサイズ
1年で250MBが多いのか少ないのかわかりませんが、3年で1.9GBになっている個人サーバーと比べれば相当小さく感じます。何度かデータ喪失しかけてるので、1日一回フルバックアップを2週間保存という感じでバックアップを保存しています。幸い24時間以上のデータ喪失や巻き戻りは発生していません。なおRedisはバックアップしていないため、時々通知やアンテナが消し飛んだりします。仕様です。ご迷惑おかけします。
## 1年での障害歴
最後に1年で発生した障害について書いておこうと思います。何度か全データが消えてバックアップから復旧したりしています。
N150とRyzenで構築したProxmoxクラスタ上にk3sを構築しています。明らかにオーバーな構成ですが、勉強を兼ねてプライベートクラウド風にしています。
### 2025年11月11日 ジョブキューが詰まる
詳細な障害報告はこちら
https://blog.usbharu.dev/posts/2025-01-11/
### 2025年1月13日 レートリミットで全員締め出される
根本的な原因不明ですが、レートリミットで管理者含めて全員締め出されました。trustProxy関係の設定かなぁと思っています。
Redisでレートリミットの設定を消し飛ばして復旧
### 2025年2月28日
2時間ほど開けなくなる
知らん間に治ってた
### 2025年3月27日~3月31日 ストレージ不足
ストレージ不足が原因でmicrok8sが崩壊 新PCへ移行後バックアップから復旧
27日に一度復旧したので油断してた状態で、28日夜に再度ダウン。29日,30日は外出していたため障害が長期化した
### 2025年6月26日
謎 1時間ほどで復旧
### 2025年7月25日
HTL以外がエラー おそらくDBが不調
知らん間に復旧してた
### 2025年8月19日 アンテナ消失
謎に復旧 Redisの問題だと思われる
知らない間にアンテナ消失して知らない間に復活する謎
### 2025年8月末 停電でシステム崩壊
おうちシステムが全て停止、Proxmoxクラスタが崩壊
Ryzen機に乗っていたVMはほぼ壊れたためN150機に残っていたデータとバックアップからMisskeyと一部のおうちシステムを復旧
ちなみにおうちシステムはまだ復旧してません
### 2025年10月22日 機械の故障
IX2215が故障したので予備に交換して復旧。15分ぐらいで復旧できました 偉い
---
書いてて思ったけど多いな…

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,88 +0,0 @@
---
author: usbharu
draft: false
categories:
- その他
date: 2026-01-06T14:27:52+09:00
tags:
- アイマス
- 旅行
keywords:
- アイマス
- 旅行
title: 2025年振り返り
relpermalink: posts/2026-01-06/
url: posts/2026-01-06/
decription: 2025年振り返り
---
あけましておめでとうございます。もう2026年になってしまいましたが、2025年を振り返ってみようと思います。
## 開発
2025年のGitHubの草はこんな感じでした。
![GitHubの草](image.png)
ちょっと夏休みあたりにMinecraftにハマりまくっていたのでごっそり穴が空いていますね。今年はもうちょっと頑張っていきたいと思います。
2025年はNext.jsとReactに再入門したり、組み込みRustでフライトシミュレーター用のコックピットを作ったりしていました。Kotlin,Rust,TypeScript,Golangと様々な方向に足を伸ばせたと思いますが、その分ロクに完成品が存在せず、これといった成果もありません。今年はまず完成させることを目指したいと思います。
開発環境も少しづつ変わってきていて、2025年前半はJetBrains IDEで全部やっていましたが少しづつVSCodeに移行しています。2026年も始まって少ししか経っていませんが、コーディングエージェントと統合されているエディタにも手を出し始めているのでこの調子で色々習得したいところです。
## 学校
Geminiに教えてもらいながら数学をやったり、今更JavaFXに入門したりしていました。一部の学校のイベント(?)にもスタッフ側として参加させてもらっていたりしますが、ちょっとモチベーションが下がってきています。そろそろ就活も始まってきているのでインターンとか行きたいな~と思っています。
## 趣味
![万博開場の水が溜まっている部分で、水が鏡のようになっていて綺麗](<PXL_20250429_084427237 (1).jpg>)
### 旅行
旅行動画を見るのが好きだった影響で自分も旅行に行きまくっていました。
- 2月 関西 あすて君と大阪近郊区間大回り乗車
- 3月 [愛知県小牧市](https://blog.usbharu.dev/posts/2025-03-07/)・[名古屋](https://blog.usbharu.dev/posts/2025-03-09/)
- 3月 [名古屋](https://blog.usbharu.dev/posts/2025-03-29/)
- 4月 [兵庫県明石市](https://blog.usbharu.dev/posts/2025-04-12/)
- 4月~8月 [万博](https://blog.usbharu.dev/posts/2025-05-17/) 計5回
- 5月 大阪 かすみPと旅マスミリオン
- 8月 名古屋 でらますシャイニーカラーズ
- 9月 [東京](https://blog.usbharu.dev/posts/2025-10-07/)
- 9月 [三重県伊勢市鳥羽市志摩市](https://blog.usbharu.dev/posts/2025-10-11/)
- 10月 [関東](https://blog.usbharu.dev/posts/2025-11-02/)
- 12月 和歌山 アドベンチャーワールド
その他色々行きましたがとりあえずこんなところでしょうか。基本的に交通費ケチケチ旅行か親の旅行コバンザメが多いのでそこまで交通費はかかっていません。ありがとう母親
### 電子工作
![alt text](IMG_0413.jpg)
高校入学あたりから放置していた電子工作を再開しました。当時お金がなくて辞めてしまったのですが、60円のユニバーサル基板を何枚買うかで10分も20分も悩んでいたあの頃とは違います。700円ぐらいでプリント基板を作ることができるので、表面実装部品だって使うことができます。すごく楽しいのですが、やりたいことに対して自分の技術力が追いついていないので今年はもっと頑張りたいところです。
## アイマス
初めてミリシタの周年イベントを走ったり、ライブに参加したりしました。コラボも行ける限りでは大体行きました。アイマス最高です。ちなみにMacBook Proが余裕で買えるぐらいアイマスにお金を使ったみたいです。やべぇな
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ミリオン初現地! <a href="https://t.co/Zruw0xfJjM">pic.twitter.com/Zruw0xfJjM</a></p>&mdash; usbharu (@usbharu_dev) <a href="https://twitter.com/usbharu_dev/status/1977244856755110232?ref_src=twsrc%5Etfw">October 12, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MOIW来た <a href="https://t.co/TMIaGwFC2I">pic.twitter.com/TMIaGwFC2I</a></p>&mdash; usbharu (@usbharu_dev) <a href="https://twitter.com/usbharu_dev/status/1999668329922068786?ref_src=twsrc%5Etfw">December 13, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
あとはアケマスをやったり、ツアマスをやったり、CDを買ったりしています。BDもいくつか手に入れたので観たいなぁ
## その他
- 20歳になったのでお酒が飲めるようになりました。今は梅酒が好きです。
- 携帯がGoogle PixelからiPhoneになりました。快適です。
- フリスクドリンクを(時には奢ってまでして)友だちに飲ませる活動をしていました。
- もう最近やっていない原神ですが、フリーナ完凸するだけしました。2025年のプレイ時間は15分です。
- 2025年に一番聞いていた曲は[Brand New Theater!](https://open.spotify.com/intl-ja/track/1fzEGXvMeutGHeCBF42pUX?si=2f45d17762c64366)でした。
- 個人的ベスト曲は[Luvliminal image](https://open.spotify.com/intl-ja/track/60n4QjCz85ljSWBaYqqnvB?si=c4215256da8942c1)です。
## 2026年の目標
<iframe src="https://misskey.usbharu.dev/embed/notes/agz6wr8adx" data-misskey-embed-id="v1_ah78gfdj8u" loading="lazy" referrerpolicy="strict-origin-when-cross-origin" style="border: none; width: 100%; max-width: 500px; height: 300px; color-scheme: light dark;"></iframe>
<script defer src="https://misskey.usbharu.dev/embed.js"></script>
あんまり関係ないですが、キーボード自作したいです。というわけで、今年もよろしくお願いします。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@ -1,116 +0,0 @@
---
author: usbharu
draft: false
categories:
- 技術
date: 2026-01-08T22:08:17+09:00
tags:
- 自動化
- Reclaim
- Google Apps Script
keywords:
- 自動化
- Reclaim
- Google Apps Script
title: スケジュール管理を自動化して怠惰を加速させる
relpermalink: posts/2026-01-08/
url: posts/2026-01-08/
decription: スケジュール管理を自動化して怠惰を加速させる
---
あるいは自分の時間を1秒でも増やしたいあなたに。
怠惰、傲慢、短気がプログラマの美徳だとか、面倒くさがりほどプログラマに向いているだとか言いますが、自動化とかすら面倒なのがusbharu。というわけで今まで課題の期限は頭で覚えて管理していました。しかし先日急激にタスクが増え、自分が管理できそうにないレベルになってしまいました。これを機に全部自動化しよう というわけです。
## 構成
- Google カレンダー
- Google Tasks
- Reclaim
- Google Apps Script(任意)
スケジュールをGoogle カレンダー、タスクをGoogle Tasks、自動化をReclaimで行います。Google Apps ScriptはiCal形式のものを自動的にGoogle Tasksにブチ込むために使うため、その他の方法で自動化できる場合は不要です。
## 自動化の準備
### スケジュール
まず、開始時間、終了時間が決まっている用事を全部Googleカレンダーに入れましょう。なに? いちいち入れるのが面倒だ? Geminiにやってもらいなさい
![GeminiにGeminiがGoogleカレンダーと連携して何ができるのかを説明してもらっている様子。予定の作成、検索、変更、削除などができる](image.png)
このとき、予定の時間ぴったりではなく拘束時間全部を登録します。なぜなら自動化の際に移動時間などは自動で計算してくれないから
なお予定自体に余裕をもたせる必要はありません。自動化の際にバッファーを設定できます。
### タスク
開始時間、終了時間が決まっていない用事、あるいは普通のタスクはGoogle Tasksに入れます。学校の課題とか、その他諸々提出物とかです。手動でタスクを追加するのはあまりにも不便なので、なんとか自動化して下さい。可能なら完了済みを反映させるところまで自動化しちゃって下さい。でもReclaimからGoogle Tasksのリストは選択できないので、連携してからReclaimが作ったリストに追加して下さい。
## いざ自動化
スケジュールの自動管理にはReclaimというサービスを使います。AIが所要時間、優先度、期限などをもとに、自動でスケジュールを組んでくれます。複数人で使う場合はそれぞれの予定を見て、会議などの時間を決めてくれる機能もあるようです。
[Reclaim](https://reclaim.ai/)
ところで公式サイトがメモリリークしていると思うんですが、僕だけでしょうか。メモリ15GB食ってました
### Reclaimに登場する概念
概念も何も一般的なスケジュール/ToDoアプリとそう変わらないのですが、いくつか特殊な概念があるのでここで説明しておきます。
- Hours - タスク、Habitsを入れて良い日、時間帯。
- Habits - 習慣 毎日、週何日、などの頻度で自動的に差し込んでくれる
- Focus - 空いてる時間にやりたいこと 例えば勉強とか、個人開発とか
#### Hours
Hoursは自動でタスクとHabitsを入れるときの制約です。タスク作成時にどのHoursでスケジュールを作成するか選ぶことができます。
![alt text](image-1.png)
Hoursを設定することで、例えば真夜中にタスクをブチ込まれる事故を防ぐことができます。あと、Googleアカウントに複数カレンダーが紐づいている場合に追加先のカレンダーを選択することができます。しっかり設定しておきましょう。家族にタスクをフル開示する事故が発生します(一敗)。
HoursにはWorking Hours、Meeting Hours、Personal Hoursの3つがデフォルトで準備されており、自分で新しく作成することもできます。僕は26時ぐらいまで起きていることが多いので、日付をまたいで設定できないのが惜しいところ
とりあえずPersonal Hoursを起きている時間全てに変えておくと良いと思います。
#### Habits
Habitsは習慣、または習慣にしたいものです。とりあえず掃除とか入れておくと良いでしょう。上で設定したHoursの時間で、設定した優先度・所要時間・理想的な時刻(Ideal time)をもとに自動でスケジューリングしてくれます。
その他スケジュールに失敗したときに残す/消すの設定や、どの程度予定を守るか、依存関係などを設定できます。
#### Focus
集中して取り組みたいことをスケジュールに組み込んでくれます。空いている時間にFocusを差し込むか、Focusを作ってから間にタスクなどを差し込むかを選べるようです。僕は後者を使っていましたが、タスクの期限よりもFocusが優先されることがあったので前者(UI上で右)にしています。
Focusは週に約何時間スケジュールするかを設定することができ、僕はとりあえず多めに設定しています。
---
さて、概念の解説が終わったところで、自動化していきましょう。設定からIntegrationに進み、Google カレンダーとGoogle Tasksを連携します。
はい、完了です。これでReclaimが自動でスケジュールを作成してくれます。Google カレンダーは今まで通り普通に予定を作成できます。人が作った予定をReclaimは尊重し、動かすことはありません。Reclaimに委ねたい場合はGoogle Tasksに追加しましょう。また、予定を移動した場合や優先度、所要時間を変更した場合に再計算が行われ、改めてスケジュールが作成されます。
あとはスケジュール結果を見て調整して行きましょう。Bufferと絵文字プレフィックスは設定しておくと良いと思います。
Googleカレンダーを見ているとき、重要な予定だけフィルターできたほうが便利ですので、手動で管理するカレンダーと自動管理するカレンダーは分けるべきでしょう。
### Google Apps Scriptで自動化
タスクの期限がiCal形式のカレンダーで配布されている場合はGoogle Apps Scriptで自動化することができます。Google カレンダーにiCal形式のカレンダーをインポートし、`CalendarApp.getCalendarById(id,now,end)`でイベント一覧を取ることができます。あとは重複排除してGoogle Tasksにブチ込むだけなのですが、タスクのタイトルでReclaimを制御することができます。
[Creating and syncing Google Tasks to Reclaim](https://help.reclaim.ai/en/articles/4293078-creating-and-syncing-google-tasks-to-reclaim)
とりあえずdueを設定しておくとよいでしょう。
[Tasks Service](https://developers.google.com/apps-script/advanced/tasks)
[Class CalendarApp](https://developers.google.com/apps-script/reference/calendar/calendar-app)
重複排除の際にはPropertiesServiceが便利です。多くても1ヶ月分のタスクなんて数百件でしょうから。
## おわりに
こんなことをしても結局TwitterとMisskeyに時間を奪われています!!!!!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,75 +0,0 @@
---
author: usbharu
draft: false
categories:
- 技術
date: 2026-01-20T09:30:58+09:00
tags:
- null
keywords:
- null
title: OpenCodeをGitHub Copilot Proで試す
relpermalink: posts/2026-01-20/
url: posts/2026-01-20/
decription: OpenCodeをGitHub Copilot Proで試す
---
最近はClaude Codeが流行っているようですが、いきなり3000円払って後悔するのもなぁ…と思っているうちにいい感じの代替が出てきました。
## インストール
OpenCodeは名前が名前だけにややこしいのですが、bun製の方のOpenCodeです。
[OpenCode 違い](https://zenn.dev/tkithrta/articles/13b576270f4d18)
↓でインストールしようとするとなんかバージョンが取得できないとか行ってエラーになるので、`npm install -g opencode-ai`でインストールしました。
```bash
curl -fsSL https://opencode.ai/install | bash
Failed to fetch version information
```
## プロバイダを接続
以下のコードを打ったらあとは指示に従います
```bash
opencode auth login
```
GitHub Copilotのページに行ってモデルを有効化しないと使えませんでした。
https://github.com/settings/copilot/features
モデルを有効化したあとopencodeの再起動が必要でした。
また、Claude Opus 4.5は有効化後しばらく待ってから新規セッションを立ち上げると使えました。
## 簡単な使い方
まぁ普通にPlanモードで実装プランを作ってもらったあと、Buildモードで実装してもらいます。プラン作成中に質問が飛んできたりするので、随時答えたり修正したりしながら続けていきます。
`ctrl+c`で終了
`opencode -c`でセッションを継続して開始
## 所感
Antigravityのときは使おうとも思わなかった(Gemini 3 Pro Highでもリミット来ないので)Gemini 3 Flashが意外と賢い
Antigravityより自走力がある
shift+enterで改行とかはできないっぽい
Claude Opus 4.5は圧倒的に賢いけど一瞬でプレミアムリクエストの枠を消費してしまう
Antigravityと比べてGemini 3 Proが遅い気がする
Claude Opus 4.5やべぇよ!!!!!(コストが)
![alt text](image.png)
GitHub Copilot Proの枠だけで何かを完成させるのは普通に無理ですね 乞食ばっかりじゃなくてClaude Codeも試そうと思いました。
Claudeに詳しそうな友人によるとOpusでPlan、SonnetでBuildがバランスが良いらしい(Claude Codeでの話だと思うが)
MCPサーバーの設定が他と違うので注意

View File

@ -1,107 +0,0 @@
---
author: usbharu
draft: false
categories:
- 技術
date: 2026-01-29T00:21:34+09:00
tags:
- 開発環境
keywords:
- 開発環境
title: MacBook環境構築2026
relpermalink: posts/2026-01-29/
url: posts/2026-01-29/
decription: MacBook環境構築2026
---
<iframe src="https://misskey.usbharu.dev/embed/notes/ahyv1dij16" data-misskey-embed-id="v1_ai2r4r3797" loading="lazy" referrerpolicy="strict-origin-when-cross-origin" style="border: none; width: 100%; max-width: 500px; height: 300px; color-scheme: light dark;"></iframe>
<script defer src="https://misskey.usbharu.dev/embed.js"></script>
去年アイマスにMacBook Proが買えるぐらいお金を使ってしまったので、反省して今年は最初にMacBook Proを買うことにしました。嘘です。
メモリが高騰しているということで、まだ影響が出ていなかったMacを買いました。最初はMac miniで考えていたのですが、やっぱ持ち運びたいよな…ということで、MacBookを選びました。
スペックはMacBook Pro(M5) 32GB/1TB です。Airのインターフェースが終わってたのでProにしましたが、流石にいい値段しました。
まだ数日しか使っていませんが、モバイル系の開発ではメモリの多さが効いてきそうです。
完全に新しい環境ということで、構築時のメモも兼ねて環境を記しておこうと思います。
## リスト
とりあえず入れたものリストです。今後増えたり減ったりします。
- brew
- nvim
- LazyVim
- lazygit
- fd
- VSCode
- JetBrains Toolbox
- Intellij IDEA
- Android Studio
- Google Chrome
- iCloudキーチェーン
- DaVinci Resolve
- Slack
- Discord
- ownCloud
- shapr3d
- zsh
- Powerlevel10k
- Oh My Zsh
- XCode
- mise
- HackGen_NF
## とりあえず先人の真似をする
Macを触るのはほぼ初めてです。というわけでタイムラインでたまたま見かけていた人の設定を真似することにしました。
といっても尖ったやつは真似せず、自分にあってそうなものだけ試しています。
### とりあえずGhosttyとmiseを採用
homebrewというのもインストールしました。よく見かけていたやつですが、自分も使うことになるとは思いませんでした。
https://brew.sh/ja/
miseではnode.jsとhugo-extendedとpnpmをインストールしました。管理については今後考えていきたいです。
WindowsではWezTermというものを使っていたんですが、なんかGhosttyの名前をよく聞くのでとりあえず使ってみることにしました。ゼロコンフィグって最高ですね
普段はデフォルトのフォントを使っていますが、なんかうまく日本語を表示できなかったので、HackGenフォントをインストールしました。
コンフィグは
```
font-family="HackGen Console NF"
```
だけ追加しています。
## NeoVimなど
普段nanoを使ってますが、正直なんでもいいのでこれも名前をよく聞くNeoVimにしました。コンフィグの盆栽をする前にやることがあるだろう ということでとりあえずLazyVimの設定を流し込んでいます。
LazyVimがらみでlazygitとfdを入れました。
lazyvimの設定は適当にTUIでやったので覚えてません。LSPとLazyExtendみたいなのをいくつか有効化しただけです。
## Google Chrome
よくわかりませんがタブの固定をしても一度閉じるとタブが消えてしまうみたいなのでよく使うタブをタブグループに放り込んで代用しています。あとはiCloudアカウントに保存されたパスワードとかを使うためにiCloudキーチェーンの拡張機能をインストールしました。 iPhoneではSafariをメインで使っていたんですが、とりあえずGoogle Chromeメインで使っていこうと思います。
## その他
Windowsと変わらず支えています。今のところRosettaはインストールせず、ネイティブだけで頑張っています。
色々やってるツリー
<iframe src="https://misskey.usbharu.dev/embed/notes/ahyw9tii3z" data-misskey-embed-id="v1_ai2qxvsf7n" loading="lazy" referrerpolicy="strict-origin-when-cross-origin" style="border: none; width: 100%; max-width: 500px; height: 300px; color-scheme: light dark;"></iframe>
<script defer src="https://misskey.usbharu.dev/embed.js"></script>
## 感想
快適の一言です。
日常使いや学校で使う分にはWindowsの方が好きかもですが、Webとかモバイルの開発するならMacはいいかもです。組み込み系の開発とか設計とかはまだ試せていないので今後試していきたいところ。不満点はわかっていた事ではあるんですが、ちょっと重いしぶ厚い事ですね。どっちもMacBook Airだと解決しとるやないかい

View File

@ -1,621 +0,0 @@
---
author: usbharu
draft: false
categories:
- 技術
date: 2026-02-01T13:07:30+09:00
tags:
- pnpm
- npm
- Tauri
- Next.js
- Biome
- Storybook
- Changesets
- TypeScript
- Renovate
- Vitest
keywords:
- pnpm
- npm
- Tauri
- Next.js
- Biome
- Storybook
- Changesets
- TypeScript
- Renovate
- Vitest
title: プロジェクトを作るときに考えたいこと
relpermalink: posts/2026-01-31/
url: posts/2026-01-31/
decription: プロジェクトを作るときに考えたいこと
---
何か新しいものを作ろうとしたときに、毎回調べている気がするのでまとめてみた。
最近はWeb(Next.js)Desktop(Tauri+Vite+React)で作ることが多いので、なんだかんだ偏っているけどnpm使うなら使えるはず
## プロジェクトの構造を作る
基本的にpnpmを使う
```bash
pnpm init --init-type module
```
モノレポでやる場合は`pnpm-workspace.yaml`を追加する
[pnpm-workspace.yamlの構文](https://pnpm.io/ja/next/pnpm-workspace_yaml)
大体こんな感じのディレクトリ構造でやることが多い desktopとwebのフォルダは`pnpm create ほにゃらら`が作るので自分では作らない
```bash
tree .
.
├── apps
│ ├── desktop
│ └── web
└── packages
├── ui
└── utils
7 directories, 0 files
```
### Next.js
こんな感じで作成する
ESLintではなくBiomeを使う
```bash
create next-app@latest web
✔ Would you like to use the recommended Next.js defaults? No, customize settings
✔ Would you like to use TypeScript? … No / Yes
✔ Which linter would you like to use? Biome
✔ Would you like to use React Compiler? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
✔ What import alias would you like configured? … @/*
```
`pnpm-workspace.yaml`と`biome.json`が作成されるが、プロジェクトルートで作成するので必要に応じて削除する。
### Tauri
Rustがインストールされていることを確認する
```bash
pnpm create tauri-app
✔ Project name · desktop
✔ Identifier · dev.usbharu.test
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
✔ Choose your package manager · pnpm
✔ Choose your UI template · React - (https://react.dev/)
✔ Choose your UI flavor · TypeScript
```
### TypeScript
```bash
pnpm add -D typescript
npx tsc --init
```
npm scriptにtypecheckを追加しておく
正直いらないが… AIが利用できるコマンドを制限するときに楽
```json
"typecheck": "tsc --noEmit"
```
### Vite(ライブラリモード)
npmに公開するかはともかくライブラリを作るときはViteのライブラリモードを利用するといいらしい やったことない
https://ja.vite.dev/guide/build#library-mode
単にモレポの1パッケージとして作るだけなら不要
---
pnpmでモレポ内のパッケージを追加する場合
```bash
pnpm add --workspace @test/ui
```
npmではやったことないけど、バージョンカタログの仕組みであるpnpm catalogで管理するというのもいいかも
https://pnpm.io/ja/catalogs
## テストとか諸々
### Biome
Biome君VSCodeの拡張機能がちょっと残念だけど基本的に優秀なので使ってます
https://biomejs.dev/ja/guides/getting-started/#%E8%A8%AD%E5%AE%9A
```bash
pnpm add -w -D @biomejs/biome
pnpm exec biome init
```
- JSONスキーマをURLからnode_modules内のファイルに変える
- 自動的にインストールされているバージョンのスキーマを使うことができる
- useIgnoreFile
- *.d.tsファイルの除外
- tailwindcss対応
```json
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!**/*.d.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"noStaticElementInteractions": "off"
},
"nursery": {
"useSortedClasses": {
"fix": "safe",
"level": "error",
"options": {
"functions": ["twMerge", "twJoin", "tv", "cn"]
}
}
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"css": {
"parser": {
"cssModules": true,
"allowWrongLineComments": true,
"tailwindDirectives": true
},
"formatter": {
"enabled": false
},
"linter": {
"enabled": false
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
```
npm scriptにlintとlint:fixを追加しておく
--unsafeオプションはご自由に 僕はつけます
```json
"scripts": {
"lint": "biome check",
"lint:fix" : "biome check --write --unsafe"
},
```
### Vitest
テストにはVitestを使う 正直そんなに使ったことない
```bash
pnpm add -D vitest
```
npm scriptにtestを追加する
```json
"scripts": {
"test": "vitest"
},
```
### Storybook
AIと色々やるときにあるとすごい便利
ReactとかのUIライブラリが依存関係に入っていないと自動作成に失敗するみたいなので注意
```bash
pnpm create storybook@latest
```
あとは画面の指示に従うだけ
Tailwindcssの設定もしておく
https://pystyle.info/react-vite-tailwind-storybook/
### Storycap
ビジュアルリグレッションテストを簡単に行えるよう、コンポーネントのスクショを自動で取れるようにしておく
AIにUIコンポーネントを触らせるときにちょっとだけ安心できる
Storycapとあるが正確には改良版のStorycap-testrunというもの
```bash
pnpm add -D @storycap-testrun/browser
```
vitest.setup.tsに以下を追記
```typescript:vitest.setup.ts
import { page } from "vitest/browser";
import { screenshot } from "@storycap-testrun/browser";
afterEach(async (context) => {
await screenshot(page, context);
});
```
vitest.config.tsのプラグインに以下を追記
```typescript:vitest.config.ts
import storycap from "@storycap-testrun/browser/vitest-plugin";
storycap({
output: {
file: (context) => `${context.id}.png`,
},
}),
```
`.gitignore`に`__screenshots__`と書いておくと良い
## Git/GitHubとCI/CD
基本的にGit Flowをちょっと省略したブランチ戦略を取る
`release`ブランチを省略(リリース作業は自動化、それ以外はdevelopでするので)
`hotfix`ブランチも省略
### Gitの設定
やっていなければリポジトリの初期化 masterとmainに注意(n敗)
```bash
git init .
```
`.gitignore`の設定
https://github.com/github/gitignore
こういうところから持ってくる
### コミット前に自動修正
lefthookとbiomeを組み合わせる
```bash
pnpm add -D -w lefthook
```
lefthook.yamlを作成する
```yaml:lefthook.yaml
pre-commit:
commands:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
stage_fixed: true
pre-push:
commands:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: npx @biomejs/biome check --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {push_files}
```
適用
```bash
pnpm lefthook install
```
### GitHub
とりあえずリポジトリを作る。masterとmainに注意 上でやった`.gitignore`はここでやってもいい
Renovateとかを有効化しておく
設定していく
- オートマージを許可
- デフォルトブランチをdevelopに
- プルリクエストブランチの更新を常に提案する
- ヘッドブランチを自動的に削除する
- Dependabot Alertsを有効にする
- ブランチプロテクションルールを作成する CIの構築をしてからの方が楽
- Masterブランチは直Push禁止
- CI全Passが必須
- バイパス禁止
- Developブランチは直Push許可
- CI全Passが必要だがバイパスを許可
- レビューが必要なら最少Approve数を設定
- チーム開発ならWebhookを設定
- Issue追加・PR追加・リリースあたりを通知してスレッド運用が良さげ 正直SlackのGitHub Appが一番いい
- Discord https://mekurun.com/tips/discord-github/
### Renovate
依存ライブラリのバージョン管理は自動化する
- minorとpatchの自動マージを有効化
- platformAutomergeを有効化
- rebaseWhenをconflictedかneverに
- lockFileMaintenanceをtrueに 正直いらんかも
```json:renovate.json
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"packageRules": [
{ "matchUpdateTypes": ["minor", "patch"], "automerge": true }
],
"platformAutomerge": true,
"rebaseWhen": "conflicted",
"lockFileMaintenance": {
"enabled": true,
"recreateWhen": "always",
"rebaseStalePrs": true,
"branchTopic": "lock-file-maintenance",
"commitMessageAction": "Lock file maintenance",
"commitMessageTopic": null,
"commitMessageExtra": null,
"schedule": ["before 4am on monday"],
"groupName": null,
"prBodyDefinitions": {
"Change": "All locks refreshed"
}
}
}
```
### Vitest
package.json内に存在している不要なtestスクリプトは削除しておく
ルートのpackage.jsonに
```json
"test:all": "pnpm -r --reporter-hide-prefix test"
```
を追記しておく
-rオプションで子プロジェクトでも再起的に実行
--reporter-hide-prefixオプションで後述するテストレポートの邪魔を防げる
簡単にテストレポートを手に入れる手段としてGitHubのアテーションを使う
https://vitest.dev/guide/reporters.html#github-actions-reporter
### VRT(ビジュアルリグレッションテスト)
AIにUIを触らせるならあったらすごく便利です
`reg-viz/reg-actions@v3`を使います。
playwrightとのインストールが必要な割に実行する必要があるタイミングが多く、コストが重め
PRのコメントに差分を投稿してくれるけど、PRのマージ先のコミットで必ずVRTが実行されている必要があるため、マージコミットにもVRTのアクションを実行する必要がある(この仕様にめちゃくちゃハマった)
残っている最新のスクショ結果ではなく、最新のコミットのスクショを探すという点に注意
簡単に書くのが凄く難しいので今動いているActionをそのまま書いておきます
`@travel-scheduler/ui`の部分をUIコンポーネントのパッケージ名に変えると動くと思います。
```yaml
name: Visual Regression Test
on:
push:
branches: [develop, main]
pull_request:
branches: [develop, main]
permissions:
contents: write
actions: write
pull-requests: write
jobs:
test:
timeout-minutes: 10
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1/3, 2/3, 3/3]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
node-version: 22
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Cache Playwright binaries
uses: actions/cache@v5
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm -F @travel-scheduler/ui exec playwright install chromium
- name: Install Playwright system dependencies
run: pnpm -F @travel-scheduler/ui exec playwright install-deps chromium
- name: Run storycap tests (shard ${{ matrix.shard }})
run: pnpm -F @travel-scheduler/ui exec vitest run --project=storybook --shard=${{ matrix.shard }}
- name: Upload screenshots
uses: actions/upload-artifact@v6
if: always()
with:
name: screenshots-${{ strategy.job-index }}
path: packages/ui/__screenshots__
retention-days: 1
compare:
needs: test
if: always()
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Download all screenshot artifacts
uses: actions/download-artifact@v7
with:
pattern: screenshots-*
path: downloaded-screenshots
- name: Merge screenshots
run: |
mkdir -p packages/ui/__screenshots__
for dir in downloaded-screenshots/screenshots-*; do
if [ -d "$dir" ]; then
cp -r "$dir"/* packages/ui/__screenshots__/ 2>/dev/null || true
fi
done
echo "Merged screenshots:"
ls -la packages/ui/__screenshots__/
- name: Upload merged screenshots
uses: actions/upload-artifact@v6
with:
name: storycap-report
path: packages/ui/__screenshots__
retention-days: 30
- name: Run visual regression comparison
uses: reg-viz/reg-actions@v3
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./packages/ui/__screenshots__"
```
### Changesetsによるバージョン管理
自分は調べながら初めて使ったけど、とても便利そう
インストール
```bash
pnpm add -wD @changesets/cli
```
初期化
```bash
npx changesets init
```
変更を追記(GitHub Appで自動化可能)
```bash
npx changesets
```
追記した変更をまとめてリリース(GitHub Actionで自動化可能)
```bash
npx changesets version
```
変更の追記の確認をしてくれるBot
https://github.com/apps/changeset-bot
masterにpushがあったら自動でリリース(changesets version)を行うAction
```yaml
name: Release
on:
push:
branches:
- master
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
permissions:
pull-requests: write
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js 20
uses: actions/setup-node@v3
with:
node-version: 22
- name: Install Dependencies
run: pnpm install
- name: Create Release Pull Request
uses: changesets/action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
### npm versionによるバージョン管理
npmではやったことないけど、Gradleでは近い方法でバージョン管理をしていた 全パッケージが同じバージョン番号を持つプロジェクトやモレポじゃないプロジェクトではGitに全部を合わせることができるので楽
https://qiita.com/minamo173/items/8b8b27bc6ecd17ad925e
masterブランチにtagがpushされたときにfrom-gitで発動させる
### GitHub Copilotによるレビューを行う
自動でレビューさせるかはともかく設定する
https://github.com/settings/copilot/features
で有効化できる
`.github/copilot-instructions.md`に日本語で頼む的な指示を書いておきましょう。
---
AI関連のことも書こうかと思ったけどだいぶ長い記事になったので一旦ここまで

View File

@ -1,53 +0,0 @@
---
author: usbharu
draft: false
categories:
- 技術
date: 2026-02-09T18:08:54+09:00
tags:
- Rust
keywords:
- Rust
title: IME用の辞書から子音抜き検索ができるコマンドを作ったよ
relpermalink: posts/2026-02-09/
url: posts/2026-02-09/
decription: IME用の辞書から子音抜き検索ができるコマンドを作ったよ
---
## Q. 子音抜きって何?
A.
```
春日未来(かすがみらい) → ksgmri
```
まぁTwitterとかでえっちな話する時に使われるやつですね
これを覚えるというか元の名前を思い出すのが苦手なので作ってみました。まぁ作ったのはGemini君なんですが
## Skltn
Skeletonから子音を抜いた名前です。
[skltn](https://github.com/usbharu/skltn)
Rust製で、手元の環境だと27万行の辞書ファイルを大体30msぐらいで検索してくれました。正直速いのかはわかりませんが…
ニコニコ大百科の内容をIME用の辞書にしたやつを使うのがおすすめです。
## 最適化
当然ですがIME用の辞書ファイルはただのテキストで、普通に検索するとなるとフルスキャンする必要があります。フルスキャンでもReleaseビルドだと意外と速かった(190ms~)んですが、流石にもっと早くできるだろうと言うことで色々最適化してもらいました。
- メモリマップIO
- 並列化
- 二分探索→インデックスファイル作成
- 早めの検索切り上げ
ほぼAIが考えた最適化の中で、唯一自分が考えた最適化が二分探索です。50音順に辞書が並んでいる前提で、1文字目を高速に検索できます。ちなみに大して速くなりませんでした。かなしい
ちなみにインデックスファイルを作成しますが、使ってもあんまり速くなりません なんでや…
![alt text](<スクリーンショット 2026-02-12 13.59.36.png>)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB