Metadata-Version: 2.4
Name: hermes-mine-bean
Version: 0.4.1
Summary: MineBean ($BEAN) round-based mining plugin for Hermes Agent
Author-email: MineBean <hey@minebean.com>
License: MIT
Project-URL: Homepage, https://minebean.com
Project-URL: Repository, https://github.com/damo-nu11/hermes-mine-bean
Project-URL: Issues, https://github.com/damo-nu11/hermes-mine-bean/issues
Keywords: hermes,agent,minebean,bean,base,mining,plugin
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: web3>=7.0
Requires-Dist: eth-account>=0.13
Requires-Dist: requests>=2.31
Requires-Dist: openai>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Provides-Extra: mcp
Requires-Dist: mcp[cli]>=1.0; extra == "mcp"
Dynamic: license-file

# hermes-mine-bean

A [Hermes Agent](https://hermes-agent.nousresearch.com/) plugin for mining $BEAN on the [MineBean protocol](https://minebean.com), live on Base mainnet.

Round-based on-chain deployment, five strategy presets, autonomous cron mode, signed Gitlawb audit log, Venice as default inference provider. Works inside Hermes Agent, Claude Desktop, Cursor, or any MCP-aware client.

> Status: v0.4.1 live on PyPI. All ten tools work against Base mainnet today, verified end-to-end inside a real Hermes Agent session. Live broadcast is opt-in behind a one-line env unlock; dry-run is the default everywhere. v0.4 adds the real Venice inference client, the agent-callable `minebean_chat` tool, multi-provider abstraction across Venice, OpenAI, Anthropic, OpenRouter, Ollama, and LM Studio, plus VVV staking awareness on Base.

## What MineBean is (60 seconds)

5x5 grid. New round every 60 seconds. Each round you pick blocks, deploy ETH into them, and earn $BEAN rewards plus an ETH share when your round closes. Roughly 1-in-777 rounds hit a beanpot jackpot. Contract addresses, agent stats, and the full game state are at [minebean.com](https://minebean.com).

This plugin gives any Hermes agent the ten tools needed to read the live game, plan deploys, broadcast them through a wallet you control, run a cron-driven autonomous miner with a hard daily ceiling, route inference through Venice (or any of five other supported providers), call the model directly via `minebean_chat`, and check VVV staking balances on Base.

## Install

Requires Python 3.11 or newer.

The recommended path is a dedicated Python virtualenv so Hermes, the plugin, and all blockchain dependencies stay isolated from the rest of your machine. Four lines from a fresh terminal:

```bash
python3 -m venv ~/hermes-mine-bean-env
source ~/hermes-mine-bean-env/bin/activate
pip install hermes-agent hermes-mine-bean
hermes plugins install damo-nu11/hermes-mine-bean --enable
```

What each step does:

1. Creates a dedicated venv (any path works, `~/hermes-mine-bean-env` is just a convention).
2. Activates the venv for this shell. Every future Hermes session needs this line first; that's how Hermes picks up the plugin's Python dependencies.
3. Installs Hermes Agent itself plus `hermes-mine-bean` (which brings `web3`, `eth-account`, and the rest of the stack into the venv).
4. Clones the plugin into `~/.hermes/plugins/minebean/` and enables it so Hermes' directory-based loader picks it up. The plugin manifest, the ten tools, the `/minebean` slash command, and the lifecycle hooks all register at agent startup.

Launch Hermes from the activated venv:

```bash
hermes
```

Inside the chat, ask the agent something like `call the minebean_status tool` and you should get live round data from Base.

If you only need the headless CLI miner (`hermes-minebean-deploy`) or the standalone MCP server (`hermes-minebean-mcp`) and not the in-Hermes plugin, just steps 1-3 are enough; you can skip the `hermes plugins install` line. For MCP add the extra at install time:

```bash
pip install "hermes-mine-bean[mcp]"
```

From source (for contributing):

```bash
git clone https://github.com/damo-nu11/hermes-mine-bean.git
cd hermes-mine-bean
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[mcp]"
```

Upstream skill registry PR is open at [NousResearch/hermes-agent#29850](https://github.com/NousResearch/hermes-agent/pull/29850); once merged, the skill becomes discoverable directly from the registry.

## Configure

Add to `~/.hermes/.env`:

```bash
# --- For broadcasting (autonomous mining) ---
# Use a dedicated wallet you fund only for this purpose. Never your main.
MINEBEAN_DEPLOYER_KEY=0x...

# --- Or readonly inspection (no key needed) ---
# MINEBEAN_MINER_ADDRESS=0x...

# Bankr-managed signing is on the v0.5 roadmap. v0.4 ships local EOA only.

# --- Safety guards (recommended) ---
MINEBEAN_MAX_DEPLOYS_PER_DAY=100
MINEBEAN_PER_BLOCK_WEI=2500000000000
MINEBEAN_MAX_DEPLOY_WEI=10000000000000000  # 0.01 ETH cap per round

# --- Strategy data feeds (defaults work for most users) ---
# MINEBEAN_BEAN_PRICE_ETH=                       # offline override, otherwise fetched from api.minebean.com
# MINEBEAN_PRICE_URL=                            # custom price endpoint
# MINEBEAN_BEANPOT_HISTORICAL_MAX_BEAN=700       # beanpot-hunter campaign cap

# --- Optional RPC override ---
# BASE_RPC_URL=https://mainnet.base.org
```

`chmod 600 ~/.hermes/.env` so other users on the machine can't read it.

**Security-sensitive env vars** (never commit, never share, never log):
- `MINEBEAN_DEPLOYER_KEY` — your wallet private key
- `MINEBEAN_LIVE_BROADCAST_UNLOCKED` — when set to `1`, enables live broadcast. Leave unset (the default) until you've personally reviewed `signer.py` and are ready to send real transactions. Treat this flag like the key itself: only set it on a machine you control, never in shared configs or CI.

## Tools

| Tool | Purpose | Signer required |
|---|---|---|
| `minebean_status` | Live round state, beanpot pool, caller's pending balances | No (works with address only) |
| `minebean_pending` | Pending ETH + BEAN for any address | No |
| `minebean_set_profile` | Save default strategy (`sniper`, `anti-winner`, `beanpot-hunter`, `anti-loser`, `nostradamus`) | No |
| `minebean_deploy` | Build deploy plan, optionally broadcast | Yes for broadcast, no for dry-run |
| `minebean_claim` | Claim pending winnings | Yes |
| `minebean_autostart` | Install autonomous mining cron job | Yes |
| `minebean_autostop` | Remove the cron job | No |
| `minebean_inference_status` | Active LLM inference provider, base URL, default model, per-provider configured map | No |
| `minebean_chat` | Send a prompt to the configured LLM provider (Venice by default). Multi-provider hook: respects `HERMES_INFERENCE_PROVIDER` and `--provider` overrides | No |
| `minebean_vvv_status` | VVV and sVVV balance for an address on Base (Venice staking awareness) | No |

Slash command: `/minebean <subcommand>`. Try `/minebean status` first to confirm everything is wired correctly. Other examples:

```
/minebean pending 0xabc...
/minebean profile sniper
/minebean inference_status
/minebean chat What's the optimal sniper block this round?
/minebean vvv_status 0xabc...
```

All write paths default to `dry_run=True` while the live broadcast gate is in place. You'll see the resolved plan, gas estimate, and ceiling status without sending a transaction.

## Strategy presets

All five strategies use the closed-form EV optimum `X* = sqrt(K × P × T) − T` where `P` is BEAN price in ETH, `T` is the relevant deployment total (strategy-specific), and `K = B / FEE_DRAG` is the strategy's EV constant.

| Preset | Blocks | T source | K | Behaviour at T ≥ threshold |
|---|---|---|---|---|
| `anti-winner` | 24 (excl. prev winner) | current grid total | 10.476 (B=1.1) | Deploy minimum for beanpot eligibility |
| `nostradamus` | All 25 | avg of last 3 settled rounds | 9.524 (B=1.0) | Skip |
| `anti-loser` | 24 (excl. coldest in last 100) | max(grid, avg of last 3) | 9.524 | Skip |
| `sniper` | All 25 | live grid at deploy time | 9.524 | Skip |
| `beanpot-hunter` | All 25 | current grid total | dynamic (B = 1 + beanpot/777) | Skip if beanpot < 62.16 BEAN |

`Beanpot-hunter` adds a campaign-sizing layer on top of the formula: deploy size scales linearly from 0.5% of wallet balance at the 62.16 BEAN threshold to the configured maximum at the historical max pot (default 700 BEAN). The EV formula acts as a floor.

`Sniper` adds adaptive binary-search timing (5s initial offset, 2-10s range, 0.5s step), applied at broadcast time. Timing supervision is left to the cron entry or an LLM supervisor running every 10 rounds.

Common floor: per-block deploy is grossed up by the 1% vault fee so the net amount clears the `MIN_DEPLOY` contract floor (0.0000025 ETH/block).

## First live broadcast

After your dev review of `signer.py` clears, walk through this once before enabling cron mode.

1. **Fund the wallet** — send ~0.005-0.01 ETH on Base to the address `MINEBEAN_DEPLOYER_KEY` resolves to. Enough for one or two anti-winner deploys plus gas.

2. **Set safety caps** in `~/.hermes/.env`:
   ```
   MINEBEAN_LIVE_BROADCAST_UNLOCKED=1
   MINEBEAN_MAX_DEPLOYS_PER_DAY=1
   MINEBEAN_MAX_DEPLOY_WEI=200000000000000   # 0.0002 ETH cap, raise after first success
   ```

3. **Load env into your shell** (whitelist the MineBean vars; skips any stray non-env-style lines):
   ```bash
   while IFS= read -r line; do
     case "$line" in
       MINEBEAN_*=*|BASE_RPC_URL=*) export "$line" ;;
     esac
   done < ~/.hermes/.env
   ```

4. **Run the broadcast interactively**:
   ```bash
   hermes-minebean-deploy --profile anti-winner --no-dry-run
   ```

5. **Verify** the JSON output:
   - `broadcast.ok: true`
   - `broadcast.stage: "confirmed"`
   - `broadcast.receipt.status: 1`
   - `broadcast.tx_hash: "0x..."` (paste into `https://basescan.org/tx/{hash}` to inspect)

6. **Raise `MINEBEAN_MAX_DEPLOYS_PER_DAY`** to your desired cap, then move to cron mode (next section).

If `broadcast.ok` is false, the `stage` field tells you exactly what failed: `sign_failed`, `broadcast_failed`, `receipt_timeout`, `reverted`, `ceiling_reached`, or `live_broadcast_blocked`. The daily counter only increments on `stage="confirmed"`, so a failed run doesn't burn quota.

## Autonomous mode

Two ways to start a scheduled miner.

**Via slash command:**

```
/minebean autostart every 60s
```

**Via Hermes cron directly:**

```bash
hermes cron add --name "MineBean deploy" --no-agent \
  --script ~/.hermes/scripts/minebean-deploy.sh "every 60s"
```

The cron entry runs `hermes-minebean-deploy`, which:

- Enforces `MINEBEAN_MAX_DEPLOYS_PER_DAY` (atomic counter under `~/.hermes/.minebean/`)
- Exits `0` on a normal skip or ceiling hit (no error spam)
- Exits `1` on a real failure
- Exits `130` on SIGINT
- Emits one JSON line per run for log scraping

Stop with `/minebean autostop` or `hermes cron remove <name>`.

## MCP server

The `[mcp]` extra ships a `hermes-minebean-mcp` console script that speaks JSON-RPC over stdio.

**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "minebean": {
      "command": "hermes-minebean-mcp",
      "env": {
        "MINEBEAN_MINER_ADDRESS": "0xYourAddress",
        "MINEBEAN_MAX_DEPLOYS_PER_DAY": "100"
      }
    }
  }
}
```

**Cursor** (`.cursor/mcp.json` in your project):

```json
{
  "mcpServers": {
    "minebean": {
      "command": "hermes-minebean-mcp"
    }
  }
}
```

Restart the client, then ask: *"What's the current MineBean round?"*

The MCP server registers all 10 tools with full schemas. Deploy and claim default to dry-run from the MCP surface too.

## Inference provider

The plugin defaults `HERMES_INFERENCE_PROVIDER=venice` when nothing is set, so any Hermes agent running this plugin routes its LLM calls through [Venice](https://venice.ai/) by default. Venice's no-log mode is platform-default at the API layer (prompts and responses are never persisted) while the mining loop stays fully on-chain and public.

Add to `~/.hermes/.env` to enable Venice:

```bash
VENICE_API_KEY=...
```

> v0.3 users: `HERMES_VENICE_API_KEY` is still recognised. The plugin bridges the legacy name to the canonical `VENICE_API_KEY` automatically at startup so existing configs keep working. Rename when convenient.

**Multi-provider hook.** Already running Hermes with a different provider? The plugin respects whatever you pin. Set `HERMES_INFERENCE_PROVIDER` to any of `venice`, `openai`, `anthropic`, `openrouter`, `ollama`, or `lmstudio` and the bootstrap leaves it alone. v0.4 ships the real OpenAI-compatible client adapter, so calls actually route through your chosen provider, not just env-default.

**Direct inference via `minebean_chat`.** v0.4 adds an agent-callable tool that sends a single prompt to the active inference provider and returns the response. Useful when the agent wants ad-hoc reasoning, a second opinion, or to route a specific call through Venice without leaving the Hermes session. Read-only — never modifies on-chain state.

**VVV staking awareness.** `minebean_vvv_status` reads the caller's VVV and sVVV balances on Base (contract addresses `0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf` and `0x321b7ff75154472B18EDb199033fF4D116F340Ff`). Useful when the agent wants to know whether the user qualifies for free Venice inference via staking. Read-only.

Inspect the active provider any time via:

```
/minebean inference_status
```

or call the `minebean_inference_status` tool directly.

## Zero-install via .well-known

You can also load this skill without `pip install` by pointing a Hermes-compatible client at:

```
https://agent.minebean.com/.well-known/skills/index.json
```

The discovery endpoint returns a SKILL.md and a minimal stdlib readonly client (`scripts/minebean_client.py`). Useful for prototyping or for clients that prefer file-based skill loading.

## Verifiability

Every round is mirrored to a signed Gitlawb repository:

```
gitlawb://did:key:z6MkwVfgaAnuypajisEkJLkVbWPiPEBwceMkGutfXpEEYHKi/minebean-rounds
```

Append-only, signed, and replicated across the Gitlawb network, with new round files landing every 5 minutes. Pull the window file for any time range to audit any outcome without trusting minebean.com.

## Safety

- `dry_run=True` is the hard default on every write path. Live broadcast requires `MINEBEAN_LIVE_BROADCAST_UNLOCKED=1`.
- `make_signer()` raises in every non-readonly branch (the broadcast path is wired but disabled at the source)
- `MINEBEAN_MAX_DEPLOYS_PER_DAY` blocks both the cron entry and the interactive deploy handler. The counter is `fcntl`-locked so overlapping crons cannot under-count.
- The GridMining contract enforces one deploy per round per address. The plugin mirrors this client-side.
- Cron wrapper script is `chmod 700` (user-only rwx) because it sources `~/.hermes/.env`.
- Readonly mode (just `MINEBEAN_MINER_ADDRESS`, no key) lets you inspect any address without putting a key anywhere.

## Network

| Field | Value |
|---|---|
| Chain | Base mainnet (chain ID 8453) |
| GridMining | `0x9632495bDb93FD6B0740Ab69cc6c71C9c01da4f0` |
| BEAN token | `0x5c72992b83E74c4D5200A8E8920fB946214a5A5D` |
| Default RPC | `https://mainnet.base.org` |

ABIs ship in `src/hermes_minebean/abi/`. The GridMining ABI is extracted from the deployed contract via BaseScan.

## Repo layout

```
hermes-mine-bean/
├── pyproject.toml             package config + entry points
├── plugin.yaml                Hermes Agent plugin manifest
├── src/hermes_minebean/
│   ├── plugin_entry.py        Hermes register(ctx)
│   ├── mcp_server.py          FastMCP server for Claude/Cursor
│   ├── cli.py                 hermes-minebean-deploy console script
│   ├── tools.py               10 tool handlers
│   ├── inference.py           inference provider bootstrap + legacy bridge
│   ├── inference_client.py    openai-compatible client for six providers
│   ├── staking.py             VVV + sVVV read-only balance queries
│   ├── schemas.py             OpenAI-style schemas + presets
│   ├── strategies.py          5 strategy resolvers
│   ├── signer.py              eoa | bankr | readonly signer abstraction
│   ├── contract.py            GridMining read + tx-builder client
│   ├── rpc.py                 web3 client with Cloudflare-safe UA
│   ├── state.py               profile + daily counter (fcntl-locked)
│   ├── cron_jobs.py           autostart / autostop wrapper management
│   ├── hooks.py               pre_llm_call keyword gate
│   ├── slash.py               /minebean dispatcher
│   └── abi/gridmining.json
└── coordinator-deliverables/  zero-install skill artifacts (served via agent.minebean.com)
```

## Development

```bash
# Activate the venv
source .venv/bin/activate

# Run the readonly smoke test against mainnet
MINEBEAN_MINER_ADDRESS=0xYourTestAddress \
  python -c "from hermes_minebean.tools import _handler_status; print(_handler_status())"

# Run the MCP server and probe with a JSON-RPC client
hermes-minebean-mcp
```

The plugin is unix-only by design (Hermes Agent itself is unix-only). The daily-counter file lock uses `fcntl`.

## Contributing

Bug reports, strategy formula proposals, and PRs welcome at the [issues page](https://github.com/damo-nu11/hermes-mine-bean/issues).

Before opening a PR:
- Keep tool signatures stable (third parties consume them)
- Note any user-visible behaviour change in the PR description
- Live broadcast changes need a separate review pass

## Acknowledgements

- [Nous Research](https://nousresearch.com/) for Hermes Agent and the plugin spec
- The [MineBean](https://minebean.com) protocol team for the on-chain game
- Anthropic for the [MCP](https://modelcontextprotocol.io) protocol that makes this work in Claude Desktop and Cursor

## License

MIT. See `LICENSE` for the full text.
