0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hermes Agent を Apple Containerで動かしてみる

0
Last updated at Posted at 2026-08-03

はじめに

Apple containerがでたので、MacOSでHermes Agentなど常駐させるには、アイドル時のリソース消費がほぼゼロ、起動が高速のApple Containerを使って隔離した環境で実行するのがいいので試してみました。

Apple Containerで起動

container run \
  --name hermes \
  --detach \
  --cpus 4 \
  --memory 8G \
  --shm-size 1G \
  -v "$HOME/.hermes:/opt/data" \
  -p 127.0.0.1:8642:8642 \
  docker.io/nousresearch/hermes-agent:latest \
  gateway run

hermes agent 基本設定

container exec -it hermes hermes setup

自分のLLM Providerを設定する

Screenshot 2026-07-27 at 14.44.11.png

Tool for CLIの設定

Screenshot 2026-07-27 at 14.46.13.png

設定完了

All your files are in ~/./:

   Settings:  /opt/data/config.yaml
   API Keys:  /opt/data/.env
   Data:      /opt/data/cron/, sessions/, logs/

設定ファイルは、 $HOME/.hermes を /opt/data にマウントしてるので、ホストマシン側で設定ファイルは確認できるようになっている。

確認

container exec -it hermes hermes auth list
openai-codex (1 credentials):
  #1  openai-codex-oauth-1 oauth   device_code exhausted (16m 48s left)

chat

container exec -it hermes hermes chat

Slack 連携

container exec -it hermes hermes slack manifest --write
Slack manifest written to: /opt/data/slack-manifest.json

Next steps:
  1. Open https://api.slack.com/apps and pick your Hermes app
     (or create a new one: Create New App → From an app manifest).
  2. Features → App Manifest → paste the contents of
     /opt/data/slack-manifest.json
  3. Save; Slack will prompt to reinstall the app if scopes or
     slash commands changed.
  4. Make sure Socket Mode is enabled and you have a bot token
     (xoxb-...) and app token (xapp-...) configured via
     `hermes setup`.

ホストマシンの~/.hermes/slack-manifest.json に作成されているので、いくつか修正する。

  • App nameはDefaultでHermes となっているので、自分の好きな名前にする
  • Dockerでローカルで作っている場合は、slash command のエンドポイントはそのまま使えないので消したい場合は一旦消す
details
{
  "_metadata": {
    "major_version": 1,
    "minor_version": 1
  },
  "display_information": {
    "name": "Hermes",
    "description": "Your Hermes agent on Slack",
    "background_color": "#1a1a2e"
  },
  "features": {
    "app_home": {
      "home_tab_enabled": false,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    },
    "bot_user": {
      "display_name": "Hermes",
      "always_online": true
    },
    "slash_commands": [
      {
        "command": "/hermes",
        "description": "Talk to Hermes or run a subcommand",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[subcommand] [args]"
      },
      {
        "command": "/btw",
        "description": "Alias for /background — Run a prompt in the background",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<prompt>"
      },
      {
        "command": "/bg",
        "description": "Alias for /background — Run a prompt in the background",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<prompt>"
      },
      {
        "command": "/start",
        "description": "Acknowledge platform start pings without a reply",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/new",
        "description": "Start a new session (fresh session ID + history)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name]"
      },
      {
        "command": "/retry",
        "description": "Retry the last message (resend to agent)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/undo",
        "description": "Back up N user turns and re-prompt (default 1)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[N]"
      },
      {
        "command": "/title",
        "description": "Set a title for the current session",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name]"
      },
      {
        "command": "/branch",
        "description": "Branch the current session (explore a different path)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name]"
      },
      {
        "command": "/compress",
        "description": "Compress conversation context (add 'here [N]' to keep recent N turns; --preview shows what would happen)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[here [N] | focus topic | --preview|--dry-run]"
      },
      {
        "command": "/rollback",
        "description": "List or restore filesystem checkpoints",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[number]"
      },
      {
        "command": "/stop",
        "description": "Kill all running background processes",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/approve",
        "description": "Approve a pending dangerous command",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[session|always]"
      },
      {
        "command": "/deny",
        "description": "Deny a pending dangerous command (optionally with a reason)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[all] [reason]"
      },
      {
        "command": "/background",
        "description": "Run a prompt in the background",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<prompt>"
      },
      {
        "command": "/agents",
        "description": "Show active agents and running tasks",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/queue",
        "description": "Queue a prompt for the next turn (doesn't interrupt)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<prompt>"
      },
      {
        "command": "/steer",
        "description": "Inject a message after the next tool call without interrupting",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<prompt>"
      },
      {
        "command": "/goal",
        "description": "Set a standing goal Hermes works on across turns until achieved",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[text | draft <text> | show | pause | resume | clear | status | wait <pid> | unwait]"
      },
      {
        "command": "/subgoal",
        "description": "Add or manage extra criteria on the active goal",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[text | remove N | clear]"
      },
      {
        "command": "/whoami",
        "description": "Show your slash command access (admin / user)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/profile",
        "description": "Show active profile name and home directory",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/sethome",
        "description": "Set this chat as the home channel",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/resume",
        "description": "Resume a previously-named session",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name]"
      },
      {
        "command": "/sessions",
        "description": "Browse and resume previous sessions",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/model",
        "description": "Switch model (persists by default)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[model] [--provider name] [--global|--session] [--refresh]"
      },
      {
        "command": "/codex-runtime",
        "description": "Toggle codex app-server runtime for OpenAI/Codex models",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[auto|codex_app_server]"
      },
      {
        "command": "/personality",
        "description": "Set a predefined personality",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name]"
      },
      {
        "command": "/footer",
        "description": "Toggle gateway runtime-metadata footer on final replies",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[on|off|status]"
      },
      {
        "command": "/yolo",
        "description": "Toggle YOLO mode (skip all dangerous command approvals)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/reasoning",
        "description": "Manage reasoning effort and display",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[level|show|hide|full|clamp]"
      },
      {
        "command": "/fast",
        "description": "Toggle fast mode — OpenAI Priority Processing / Anthropic Fast Mode (Normal/Fast)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[normal|fast|status]"
      },
      {
        "command": "/voice",
        "description": "Toggle voice mode",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[on|off|tts|status]"
      },
      {
        "command": "/memory",
        "description": "Review pending memory writes / toggle the approval gate",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[pending|approve|reject|approval] [id|on|off]"
      },
      {
        "command": "/bundles",
        "description": "List skill bundles (aliases /<name> for multiple skills)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/learn",
        "description": "Learn a reusable skill from anything you describe (dirs, URLs, this chat, notes)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<what to learn from>"
      },
      {
        "command": "/suggestions",
        "description": "Review suggested automations (accept/dismiss)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[accept|dismiss N | catalog]"
      },
      {
        "command": "/blueprint",
        "description": "Set up an automation from a blueprint template",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[name] [slot=value ...]"
      },
      {
        "command": "/curator",
        "description": "Background skill maintenance (status, run, pin, archive, list-archived)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[subcommand]"
      },
      {
        "command": "/kanban",
        "description": "Multi-profile collaboration board (tasks, links, comments)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[subcommand]"
      },
      {
        "command": "/reload-mcp",
        "description": "Reload MCP servers from config",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/reload-skills",
        "description": "Re-scan ~/.hermes/skills/ for newly installed or removed skills",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/commands",
        "description": "Browse all commands and skills (paginated)",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[page]"
      },
      {
        "command": "/help",
        "description": "Show available commands",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/restart",
        "description": "Gracefully restart the gateway after draining active runs",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/usage",
        "description": "Show token usage and rate limits for the current session",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/insights",
        "description": "Show usage insights and analytics",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "[days]"
      },
      {
        "command": "/platform",
        "description": "Pause, resume, or list a failing gateway platform",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands",
        "usage_hint": "<pause|resume|list> [name]"
      },
      {
        "command": "/update",
        "description": "Update Hermes Agent to the latest version",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      },
      {
        "command": "/version",
        "description": "Show Hermes Agent version",
        "should_escape": false,
        "url": "https://hermes-agent.local/slack/commands"
      }
    ],
    "assistant_view": {
      "assistant_description": "Chat with Hermes in threads and DMs."
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "bot_events": [
        "app_mention",
        "assistant_thread_context_changed",
        "assistant_thread_started",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim"
      ]
    },
    "interactivity": {
      "is_enabled": true
    },
    "org_deploy_enabled": false,
    "socket_mode_enabled": true,
    "token_rotation_enabled": false
  }
}

Slack マニフェストからSlack Appを作成しインストールして、Bot tokenとApp tokenを取得する

  • Bot token: xoxb-xxxxx
  • App token: xapp-xxxxx

Hermes Agentに設定する

container exec -it hermes hermes setup

Screenshot 2026-08-03 at 11.42.11.png

上で取得したトークンをセットする

Screenshot 2026-08-03 at 11.45.43.png

Gatewayをリスタートすると

container exec -it hermes hermes gateway restart

Default Slackチャンネルにメッセージが投稿され連携が確認できる。

Screenshot 2026-08-03 at 11.51.51.png

話しかけてみると返事が返ってくる

Screenshot 2026-08-03 at 11.52.38.png

GitHub設定

今回はgh コマンドを使った接続をしてみます。

hermes agent のイメージにはgh コマンドが入ってないのでDockerfileを用意する

FROM docker.io/nousresearch/hermes-agent:latest

# TARGETARCH は BuildKit が自動で埋める (Apple Silicon なら arm64)
ARG TARGETARCH=arm64
ARG GH_VERSION=2.97.0
ARG GH_SHA256_arm64=73ea440ecad9c9e284429997ee6f93577bc6f7bc6fba357ef62c53ad8fb641a5
ARG GH_SHA256_amd64=a2c9b8497e1f85b1ad0dfcb78b5a622e098801b8e461e459e88e1ee12f018112

RUN set -eux; \
    case "${TARGETARCH}" in \
      arm64) gh_sha="${GH_SHA256_arm64}" ;; \
      amd64) gh_sha="${GH_SHA256_amd64}" ;; \
      *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
    esac; \
    tarball="gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz"; \
    curl -fsSL -o "/tmp/${tarball}" \
      "https://github.com/cli/cli/releases/download/v${GH_VERSION}/${tarball}"; \
    echo "${gh_sha}  /tmp/${tarball}" | sha256sum -c -; \
    tar -xzf "/tmp/${tarball}" -C /tmp; \
    install -m 0755 "/tmp/gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh" /usr/local/bin/gh; \
    rm -rf "/tmp/${tarball}" "/tmp/gh_${GH_VERSION}_linux_${TARGETARCH}"; \
    gh --version

ENV GH_CONFIG_DIR=/opt/data/gh

これでbuildして再起動します。

gh 認証:

container exec -it hermes gh auth login
? Where do you use GitHub? GitHub.com
? What is your preferred protocol for Git operations on this host? HTTPS
? Authenticate Git with your GitHub credentials? Yes
? How would you like to authenticate GitHub CLI? Login with a web browser

! First copy your one-time code: XXXX-XXXX
Press Enter to open https://github.com/login/device in your browser...
✓ Authentication complete.
- gh config set -h github.com git_protocol https
✓ Configured git protocol
! Authentication credentials saved in plain text
✓ Logged in as youraccount

chat から聞いて確認:

container exec -it hermes hermes chat
────────────────────────────────────────
● 私が最近作成したprは?
Initializing agent...
────────────────────────────────────────

  ┊ 📚 skill     github-pr-workflow  0.1s
  ┊ 📚 skill     github-auth  0.1s
  ┊ 💻 $         true) printf '\n-- gh version --\n' (gh --version + 1 command  0.7s
  ┊ 💻 $         git branch --show-current 2>/dev/null + 1 command  0.1s
  ┊ 💻 $         set -e gh search prs --author @me --sort created --order desc --limit 10 --json number,title,url,repository,createdAt,state  1.7s

╭─ ⚕ Hermes ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
    あなたの GitHub アカウントで最近作成した PR の上位10件です(作成日時の新しい順):
    ...

これで接続確認完了

GitHubの連携はGitHub Appを用いたほうが好ましいですが、今回はローカルで接続確認のために gh auth loginで認証しています。

まとめ

一旦SlackとGitHubがつながったので、Slack側から自分のAI personal assistantに何かGitHubへの操作などを依頼できるようになりました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?