Hi there 👋

SRE に憧れているインフラエンジニアの備忘録

OpenCode と ローカルLLM を試してみる

今回は、OpenCode とよばれる OSS の AI エージェント + LLM API を活用して、 コスパよいローカルAIエージェント環境を作っていきたいと思います。 OpenCode とは OpenCode は、ソフトウェアエンジニアリングタスクを支援するために設計されたオープンソースの AI エージェントです。 ターミナル上で動くため、どんなエディタにも対応します。僕は普段 Neovim で作業しているため、ターミナルで完結できるので使いやすいと感じます。 Big Pickle OpenCode では、インストール後からそのまま使えるフリーの LLM “Big Pickle” が提供されています。 このモデルで色々と使ってみましたが、複雑・難解なタスクはわかりませんが、簡単なタスク・インプットが豊富なタスクは十分実用レベルと感じました。日本語でいけます。 Zen Curated list of models provided by OpenCode. OpenCode ローカルLLM を試す 今回は、無料で使えるローカルLLMの OpenCode 上でのセットアップの手順を紹介します。 ローカルLLM をローカル環境で動かすためのランタイムとして Ollama と LM Studio を試してみます。 Ollama Ollama ダウンロードページに移動します。 Download Ollama on macOS Download Ollama for macOS インストール確認 ollama --version ollama version is 0.15.1 gemma3 をダウンロードしてみます。 ollama pull gemma3 ダウンロードされました。 ...

January 25, 2026 · 3 min · Me

Dependabot でパッケージを自動アップデートする

はじめに Dependabot とは、GitHubが提供するセキュリティツールです。リポジトリの依存関係を監視し、脆弱性のあるパッケージや古いバージョンを検知して自動でプルリクエストを作成してくれます。 サプライ チェーンのセキュリティに関するリファレンス - GitHub ドキュメント GitHub Docs 実際に Dependabot を使って、脆弱性のあるパッケージを自動アップデートしてみましょう。 まずは、dependabot の設定ファイルを以下のように作ってみます。 version: 2 updates: # Enable version updates for npm - package-ecosystem: "npm" directory: "/" # Check the npm registry for updates at 09:00 JTC 00:00 UTC on Monday schedule: interval: "weekly" day: "monday" time: "00:00" open-pull-requests-limit: 5 # Add labels to pull requests labels: - "dependencies" - "npm" # Enable version updates for GitHub Actions - package-ecosystem: "github-actions" directory: "/" # Check for updates at 09:00 JTC (00:00 UTC) on Monday schedule: interval: "weekly" day: "monday" time: "00:00" open-pull-requests-limit: 3 # Add labels to pull requests labels: - "dependencies" - "github-actions" # Assign Dependabot as a reviewer for consistency assignees: - "dependabot[bot]" reviewers: - "dependabot[bot]" これで、Dependabot によって PR が自動で作成されるようになります。 この段階だと PR が作成されるだけなので、手動でPRをマージする必要があります。 これを自動化するため、GitHub Actions で自動マージされるように設定します。 ...

January 24, 2026 · 2 min · Me

Cloudflare Workers + Next.js + KV を試してみる

以下の記事で D1 を試しましたが、KV (Workers KV) も触ってみましょう。 Cloudflare Workers + Next.js + D1 + drizzle を試してみる はじめに 最近よく Cloudflare を使っています。使いやすさ、無料枠の大きさにとても感動しています。 (こちらのブログも Cloudflare Pages で配信しています) また、普段の仕事ではよく Next.js を利用しており、Next.js on Cloudflare Workers が個人開発においては 今のところ最強なんじゃないかと思っています。 ということで、Cloudflare Workers + Next.js + D1 (とdrizzle)で開発する際の基本的な流れを紹介していきます。 今回紹介するサンプルコードの全量は以下にあります。 a2-ito/cf-db-test This repository is a minimal and practical example of running Next.js App Router on Cloudflare Workers and using D1 Database with Drizzle ORM. - a2-ito/cf-db-test GitHub テンプレートの準備 以下のコマンドを実行し、テンプレートを作成します。 wrangler は適当にインストールしておいてください。 wrangler init my-app カテゴリに Framework Starter を選択し、フレームワークとして Next.js を選択します。 コマンド実行結果 ⛅️ wrangler 4.56.0 (update available 4.58.0) ───────────────────────────────────────────── 🌀 Running `npm create cloudflare@^2.5.0 my-app --`... Need to install the following packages: [email protected] Ok to proceed? (y) y > npx > @a2ito ちなみに、KVとD1 の料金を比較すると、D1の方が圧倒的に安いです。 感覚的にはD1の方が高いのではないか、と考えていたので意外でした。D1を積極的に使いましょう。 ...

January 18, 2026 · 3 min · Me

Hugo でコードブロックをコピペできるようにする&タイトルをつける

GitHub や Zenn などでは当たり前のようにできるコードブロックのコピーですが、 Hugo 上ではデフォルトでできません。さすがに不便すぎるので作っていきましょう。 ついでに、ファイルパスを表示できるようにしましょう。 こんな感じです これを markdown 上で表現するには以下のように書きます。 ```text {data-filename="ファイル名をつけられます"} こんな感じです ``` 変更・追加するファイルはそれぞれ以下になります。 コピーボタン追加 layout/partials/head.html static/css/code-copy.css static/js/code-copy.js ファイル名追加 layout/partials/head.html static/css/code-copy.css <link rel="stylesheet" href="/css/code-copy.css"> <link rel="stylesheet" href="/css/highlight.css"> .code-block { position: relative; } .copy-btn { position: absolute; top: 2px; right: 12px; padding: 4px 8px; font-size: 0.75rem; border-radius: 6px; background: #1e293b; color: #fff; border: none; cursor: pointer; opacity: 0.8; z-index: 10; } .copy-btn:hover { opacity: 1; } document.addEventListener("DOMContentLoaded", () => { const blocks = document.querySelectorAll("pre > code"); blocks.forEach((code) => { const pre = code.parentElement; // すでに処理済みならスキップ if (pre.parentElement.classList.contains("code-block")) return; const wrapper = document.createElement("div"); wrapper.className = "code-block"; // ファイル名要素の作成 const highlight = pre.closest(".highlight"); if (highlight && highlight.dataset.filename) { const filename = document.createElement("div"); filename.className = "code-filename"; filename.textContent = highlight.dataset.filename; wrapper.appendChild(filename); } const button = document.createElement("button"); button.className = "copy-btn"; button.textContent = "Copy"; button.addEventListener("click", async () => { await navigator.clipboard.writeText(code.textContent); button.textContent = "Copied!"; setTimeout(() => (button.textContent = "Copy"), 1500); }); pre.parentNode.insertBefore(wrapper, pre); wrapper.appendChild(button); wrapper.appendChild(pre); }); }); .highlight[data-filename] { position: relative; padding-top: 0; } .code-filename { position: relative; padding: 6px 12px; font-size: 0.75rem; font-family: monospace; background: #0f172a; color: #e5e7eb; border-bottom-right-radius: 8px; user-select: text; cursor: text; }

January 17, 2026 · 1 min · Me

Hugoで利用できるブログカードを作った

Hugo 上で何かのリンクを貼ると↓のようになります。 https://github.com/a2-ito/cf-db-test これだと殺風景なので、Zenn などで自動作成されるブログカードのように装飾してみます。 実際に作ったものがこちら↓ a2-ito/cf-db-test This repository is a minimal and practical example of running Next.js App Router on Cloudflare Workers and using D1 Database with Drizzle ORM. - a2-ito/cf-db-test GitHub 基本的に AI に作ってもらったのですが、いくつか微調整しました。 OGP 画像は 160x120 の領域に拡大して収めています。(比率が違う画像の場合、引き伸ばされた感で微妙です、、、) GitHub リポジトリの場合、ogp:title にリポジトリ名と説明が含まれるようで、リポジトリ名だけを title として抽出・表示しています。 description が長い場合、カードが縦に伸びてしまうので、2行を超えないよう3行目以降は … と表示されるようにしています。 使い方としては、以下の2ファイルをコピペで配置してもらえればOKです。 assets/css/linkcard.css layouts/_shortcodes/linkcard.html a.link-card { box-shadow: none !important; } .link-card { display: flex; gap: 8px; border-radius: 12px; background: #0b2a4a; color: #fff; text-decoration: none; margin: 1.5em 0; } .link-card:hover { opacity: 0.9; } .link-card__body { flex: 1; min-width: 0; padding: 12px; } .link-card__title { font-weight: 700; font-size: 1.05rem; margin-bottom: 4px; } .link-card__desc { font-size: 0.9rem; opacity: 0.85; margin-bottom: 6px; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .link-card__site { font-size: 0.75rem; opacity: 0.6; } .link-card__image { width: 160px; height: 120px; overflow: hidden; flex-shrink: 0; background: #0a1e33; /* 余白用 */ display: flex; align-items: center; justify-content: center; } .link-card__image img { width: 100%; height: 100%; display: block; border-radius: 0px 8px 8px 0px; } layouts/_shortcodes/linkcard.html ...

January 17, 2026 · 2 min · Me