hawksnowlog
2026年7月7日火曜日
2026年7月6日月曜日
2026年7月4日土曜日
codex を Ubuntu で動かす場合のサンドボックス設定
概要
自動化する場合には書き込めるように codex がサンドボックスを作成できるようにしてあげる必要があります
環境
- Ubuntu 24.04
- codex 0.142.5
主なエラー
Unfortunately, I **cannot execute any commands** in this environment — the sandbox is rejecting all shell execution with:
bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted
This means I cannot:
- Read the actual file contents
- Apply patches
- Run tests
Could you check if there's a sandbox configuration issue? Once commands can run, I can implement the fix directly. Alternatively, if you can share the contents of the two files, I can produce the exact patch needed.
Codex's Linux sandbox uses bubblewrap and needs access to create user namespaces.
対処方法
-
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
以下で確認し 0 になっていれば OK です
- sudo sysctl kernel.apparmor_restrict_unprivileged_userns
0
インスタンスの再起動などは不要です
最後に
danger-full-access は可能な限りやめましょう
名前的にもやばいオプション名なので
参考サイト
2026年7月3日金曜日
Codex + LiteLLM + カスタムOpenAIエンドポイントの設定方法
概要
素の OpenAI エンドポイントではなく特定の環境でラップされている URL の場合には LiteLLM を挟みましょう もしくは API が完全非互換でなかったり https プロトコルのみ提供されている場合なども LiteLLM を挟むと解決することがあります
環境
- Ubuntu 24.04
- codex 0.142.5
- LiteLLM 1.90.0
LiteLLM 設定
api_base と api_key に自身の環境のカスタムOpenAIエンドポイントとカギを設定しましょう
- vim litellm/litellm_config.yaml
model_list:
- model_name: claude-chatAI
litellm_params:
model: anthropic/claude-sonnet-4-6
api_base: https://your-api-endpoint
api_key: xxx
max_tokens: 4096
temperature: 0.2
server_settings:
port: 4000
- vim litellm/compose.yaml
services:
litellm:
image: docker.litellm.ai/berriai/litellm:latest
container_name: litellm
ports:
- "4000:4000"
volumes:
- ./litellm_config.yaml:/app/config.yaml
restart: unless-stopped
command: ["--config", "/app/config.yaml"]
- docker compose up -d
codex 設定
base_url は LiteLLM が Listen しているアドレスで env_key は下記の SONNET_API_KEY を指定します
LiteLLM 側で認証情報を指定していますが一応 codex 側でも鍵情報を指定するためです
- vim ~/.codex/litellm.config.toml
model_provider = "litellm"
model = "anthropic/claude-sonnet-4-6"
web_search = "disabled"
[model_providers.litellm]
name = "sonnet"
base_url = "http://localhost:4000"
env_key = "SONNET_API_KEY"
wire_api = "responses"
動作確認
export SONNET_API_KEY="xxx"codex --profile litellm
これでインタラクティブモードで起動するので「test」など投げて応答がくれば OK です
最後に
たぶん OpenInterpreter も同じ方法でいけます
--full-auto オプションなどは廃止になっているの注意しましょう
参考サイト
2026年7月2日木曜日
OpenInterpreter や codex でカスタムエンドポイントURLを指定する方法
概要
基本は config.toml に各方式になっています
環境変数 (OPENAI_BASE_URl)や --base_url は使いません
環境
- OpenInterpreter 0.0.17
- codex 0.142.5
~/.codex/mygpt.config.toml
model_provider = "mygpt"
model = "gpt-5.1"
[model_providers.mygpt]
name = "GPT5"
base_url = "https://your-api-endpoint"
env_key = "GPT5_API_KEY"
wire_api = "responses"
基本はプロファイルと後に作成します
config.toml は全体で共通の設定を記載するの個別のプロファイル別の情報は書きません
実行方法
env_key で指定した環境変数名に API キーを設定します
export GPT5_API_KEY="xxx"codex --profile mygpt
最後に
codex の部分をそのまま openinterpreter に書き換えれば OpenInterpreter でも使えます
参考サイト
2026年7月1日水曜日
golang のテクニックとかイディオムとかメモ
概要
忘れないようにメモです
気づいたことは随時追記します
基本的な使い方というよりかは実務で使えそうな中から上級者よりの内容を記載しています
基本的な文法というよりかは設計時に使えるテクニックなどを紹介しています
環境
- macOS 26.5.1
- golang 1.26.4
interface について
- 使う目的は「差し替え可能」にするため
- 簡単に言えばテスト用 -> 結果としてテストのためになっている
- シンプルな interface にしなければならない
- メソッドは 1 or 2 個くらい (必要最低限の原則)
- 明示的な継承などは golang ではしない (できない)
- 同じ振る舞いを持つ struct の代替になれる
- golang が自動的に判断してくれる
type RedisClient interface {
LRange(ctx context.Context, key string, start, stop int64) *redis.StringSliceCmd
LPush(ctx context.Context, key string, values ...interface{}) *redis.IntCmd
Del(ctx context.Context, keys ...string) *redis.IntCmd
}
type RedisRepository struct {
client RedisClient
}
func NewRedisRepository(client RedisClient) *RedisRepository {
return &RedisRepository{client: client}
}
interface の置き場所
- 基本が使う側に定義する
- これが不思議な感じがするが golang のルールでそうなっている
- 使う側で振る舞いが柔軟に変更できるようになる
- 共通インタフェースは「一番内側(ドメイン or アプリケーション層)」に置く
- インタフェースの構成が変わっても影響しないのであればまとめて OK
- この場合は使う側ではなく使われる側に置く
interfaceは「後から作る」
- 最初からinterfaceを作らない
- 使う側が必要になったときに作る
- golang の哲学らしい
継承っぽいことをしたい場合は embedding
- struct 内のメンバーに別の struct を値レシーバで定義すると勝手にそっちのメソッドを使えるようにしてくれる
- structを埋め込むとメソッドが昇格(promotion)される
- 値でもポインタでも挙動は変わる
type Controller struct {
controller.BaseController
memoService *service.MemoService
}
とすると Controller 側で BaseController 側のメソッドが c.CurrentUsername() という感じで使える
func (c *BaseController) CurrentUsername() string {
if name := c.GetSession("user"); name != nil {
if username, ok := name.(string); ok {
return username
}
}
return "anonymous"
}
New するメソッド (コンストラクタ) は基本的にポインタ型を使う
- ポインタ型を使うとコピーではなく参照になるので具現化した大元の値まで書き換えされる
func NewController(svc *service.MemoService) *Controller {
return &Controller{memoService: svc}
}
値レシーバとポインタレシーバ
- 値レシーバとポインタレシーバでinterfaceの満たし方が変わる
- どちらのレシーバを使ってメソッドを定義したかによって参照を渡すか値を渡すか決まる
以下のような場合は参照を渡さないとインタフェースを満たさないのでダメ
type I interface {
Foo()
}
type S struct {}
func (s *S) Foo() {}
上だとエラーになる
var i I = S{} // NG
var i I = &S{} // OK
メソッドと関数は違う
- 簡単に言えばメソッドは struct 配下
- 関数は struct とは関係ない単独の関数
- メソッドは状態(struct)に紐づく振る舞い
- 関数は純粋な処理(副作用なしが理想)
メソッド
func (c *Controller) Login() {
c.LogAccess("Login")
c.RenderLayout("account/login.tpl")
}
関数
関数はレシーバの指定がない=特定の struct 配下にいない
func Replace(str string, from string, to string) string {
return strings.Replace(str, from, to, -1)
}
lazy init はある
- sync.OnceValue を使うのが基本
- 使うケースはデータベースや外部リソース接続時
- それ以外のケースでは golang では基本的には DI or DIP を使う
- struct 内のメンバーを初期化する場合に lazy init はあまり使わない
以下のような golang では書き方はあまりしない
例: ListText が呼ばれたときに初めて textService が初期化される
type MemoService struct {
textService *textsvc.Service
}
func (s *MemoService) textSvc() *textsvc.Service {
if s.textService == nil {
s.textService = textsvc.NewService(s.repo.Text())
}
return s.textService
}
func (s *MemoService) ListText(ctx context.Context, username string) ([]string, error) {
return s.textSvc().List(ctx, username)
}
generics について
- 使うケースとしては同じ振る舞いで異なる型の引数や返り値を返す場合に使うと処理を1つにまとめられる
- 可読性的には落ちる気がする
- T が直感的になるまで大変
- T が何の最終的に何の型になのか一見してわからない
- 型安全な共通処理を作るため
- interfaceでは表現できない「型の制約」を扱える
これを
func SumInt(a, b int) int {
return a + b
}
func SumFloat(a, b float64) float64 {
return a + b
}
こうできるのがジェネリクス化
func Sum[T int | float64](a, b T) T {
return a + b
}
internal ディレクトリについて
- モジュール外に公開されない機能
- 同一モジュール内でのみimport可能
- パッケージ境界を強制できるのがメリット
- internal 配下にコードを置くと勝手にそうなってくれる
- Python も
__init__.pyのスコープあり版のイメージ - Web アプリとか作成していると基本全部 internal 配下においても問題はないので internal が肥大化しないように注意しなければならない
- 例えばデータベースに関する処理だけ置くとか
- internal/database/database.go
DIP しやすい
- golang は全体的に interface に依存させるほうがベストプラクティスになるケースが多い
- そうなると自然と DIP となりクリーンアーキテクチャよりの設計に勝手になっていく印象
- クリーンアーキテクチャの話になると下位から上位の意識がかなり大事になるので厳密には必ずなるわけではない
- 書きやすいというレベル
例
// application(上位層)
type PaymentClient interface {
Charge()
}
type PaymentService struct {
client PaymentClient
}
// infrastructure(下位層)
type StripeClient struct {}
func (s *StripeClient) Charge() {}
error は特別な存在(例外がない)
- Goには例外(try-catch)がない
- errorは戻り値として扱う
- 明示的に処理するのが前提
- errors.Is / errors.As を使う
- エラーをラップする (
fmt.Errorf("%w", err))
v, err := DoSomething()
if err != nil {
return err
}
最後に
golang は他の言語に比べてルールというかイディオム的なのが多い気がします
参考サイト
2026年6月29日月曜日
Go + gin でハンドラ関数を struct にし interface 化もする
概要
これまでアクション用のハンドラ関数は struct にせずに関数だけを定義しました
テストなども考えると struct にし更に interface を定義することで管理も容易になります
環境
- macOS 26.5.1
- golang 1.26.4
- gin 1.12.0
アクション関数のサービス化と struce/interface 化
アクション関数をサービスに移動します
ユースケースと同じような扱いですが今回はわかりやすくサービスに移動します
またアクション関数は gin や http に依存しないように修正します
そしてそれぞれのアクション関数を struct として定義します
更にアクション関数が持つべき関数などを interface として定義します
- vim service/action.go
package service
import (
"fmt"
"strconv"
)
type Action interface {
Execute(params map[string]string, method string) (any, error)
}
type HelloAction struct{}
func (a *HelloAction) Execute(params map[string]string, method string) (any, error) {
name := params["name"]
if name == "" {
name = "guest"
}
return map[string]string{
"message": "hello " + name,
}, nil
}
type SumAction struct{}
func (a *SumAction) Execute(params map[string]string, method string) (any, error) {
aVal, err := strconv.Atoi(params["a"])
if err != nil {
return nil, fmt.Errorf("invalid parameter 'a'")
}
bVal, err := strconv.Atoi(params["b"])
if err != nil {
return nil, fmt.Errorf("invalid parameter 'b'")
}
return map[string]interface{}{
"a": aVal,
"b": bVal,
"sum": aVal + bVal,
}, nil
}
dispatcher の修正
dispatcher は interface を使用するように修正します
- vim handler/dispatcher.go
package handler
import (
"errors"
"gin-sample/service"
)
type Dispatcher struct {
actions map[string]service.Action
}
func NewDispatcher() *Dispatcher {
return &Dispatcher{
actions: make(map[string]service.Action),
}
}
// アクション登録
func (d *Dispatcher) Register(name string, action service.Action) {
d.actions[name] = action
}
// 登録されたアクションに紐づくハンドラ関数の実行
func (d *Dispatcher) Execute(name string, params map[string]string, method string) (any, error) {
if action, ok := d.actions[name]; ok {
return action.Execute(params, method)
}
return nil, errors.New("unknown action: " + name)
}
main.go の修正
dispatcher に登録するハンドラは関数から struct に変更します
登録する際は interface ではなく実装したそれぞれの struct 版のアクションを定義します
渡しているのは Action interfaceを満たす構造体のポインタを渡す必要があります
- vim main.go
package main
import (
"gin-sample/handler"
"gin-sample/middleware"
"gin-sample/service"
"github.com/gin-gonic/gin"
)
func main() {
dispatcher := handler.NewDispatcher()
// ★ handlerから登録
dispatcher.Register("Hello", &service.HelloAction{})
dispatcher.Register("Sum", &service.SumAction{})
r := gin.Default()
r.Use(middleware.ErrorHandler())
r.GET("/", handler.Wrap(handler.HandleAction(dispatcher)))
r.POST("/", handler.Wrap(handler.HandleAction(dispatcher)))
r.Run()
}
アクションハンドラ
これは今まで通りです
- vim handler/action_handler.go
package handler
import (
customError "gin-sample/error"
"gin-sample/model"
"github.com/gin-gonic/gin"
)
type AppHandler func(c *gin.Context) error
func Wrap(h AppHandler) gin.HandlerFunc {
return func(c *gin.Context) {
if err := h(c); err != nil {
c.Error(err) // middlewareに流す
}
}
}
func HandleAction(dispatcher *Dispatcher) AppHandler {
return func(c *gin.Context) error {
requestID := c.GetHeader("X-Request-Id")
if requestID == "" {
requestID = "dummy-request-id"
}
// パラメータ統合
if err := c.Request.ParseForm(); err != nil {
return customError.New("INVALID_REQUEST", "invalid request", 400)
}
params := make(map[string]string)
for key, values := range c.Request.Form {
if len(values) > 0 {
params[key] = values[0]
}
}
actionName := params["Action"]
result, err := dispatcher.Execute(actionName, params, c.Request.Method)
if err != nil {
return err
}
// 成功時だけレスポンスを書く
model.RespondSuccess(c, gin.H{
"requestId": requestID,
"action": actionName,
"result": result,
})
return nil
}
}
動作確認
- gofmt -w . && go run main.go
curl -X POST http://localhost:8080 -d "Action=Sum&a=1&b=2"
{"success":true,"data":{"action":"Sum","requestId":"dummy-request-id","result":{"a":1,"b":2,"sum":3}}}
curl -X GET "http://localhost:8080?Action=Hello"
{"success":true,"data":{"action":"Hello","requestId":"dummy-request-id","result":{"message":"hello guest"}}}
最後に
DI を使うようなケースでは可能な限り struct として定義したほうがテストがしやすいです
更に同じような振る舞いがある場合は interface として定義依存関係を interface 経由にするとより管理がしやすいです
ちなみにこういった interface に依存性を持たせる手法を DIP といったりします

