refactor: decouple Coin Hunter from Hermes for cross-platform usage
- Add unified coinhunter_shim.py that accepts subcommands (pre/gate/review/rotate-log) - Update SKILL.md gate pseudocode to read optional ~/.coinhunter/platform.json - Split cron/setup examples into Hermes and OpenClaw variants across docs - Introduce platform.json schema in user-data-layout.md - Remove stale auto_trader.py/run_trader.sh references from auto-trading-guide.md - Keep legacy shims as backward-compatible wrappers
This commit is contained in:
114
CLAUDE.md
Normal file
114
CLAUDE.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Repository purpose
|
||||||
|
|
||||||
|
This is a **cross-platform skill package** for a short-term crypto trading framework called Coin Hunter. It runs on Hermes, OpenClaw, and compatible cron-based runtimes. It contains the skill specification, reference playbooks, and runtime shim templates.
|
||||||
|
|
||||||
|
The actual trading CLI is an **external dependency**: the `coinhunter` package on PyPI. All execution flows through the installed `coinhunter` command. This repository does **not** contain the CLI source code or a build system.
|
||||||
|
|
||||||
|
## Repository structure
|
||||||
|
|
||||||
|
- `SKILL.md` — The canonical behavior specification. This is the source of truth for the trading framework, including the scientific checklist, execution workflow, review workflow, auto-trading architecture, low-cost gate design, production hardening rules, and troubleshooting notes.
|
||||||
|
- `README.md` — User-facing quick-start and overview.
|
||||||
|
- `references/` — Trading playbooks and templates:
|
||||||
|
- `short-term-trading-framework.md` — Hybrid strategy (70% mainstream scalping / 30% meme rotation) and position-sizing rules.
|
||||||
|
- `provider-playbook.md` — Data source hierarchy (Bybit → DexScreener → Birdeye → CoinGecko) and token identity hygiene.
|
||||||
|
- `user-data-layout.md` — Schema for private runtime state under `~/.coinhunter/`.
|
||||||
|
- `review-template.md` — Hourly review report structure.
|
||||||
|
- `scam-signals.md` — Red flags and classification guidance for meme-coin evaluation.
|
||||||
|
- `auto-trading-guide.md` — Legacy-oriented guide for deploying `auto_trader.py` and Binance API setup.
|
||||||
|
- `templates/` — Thin shim scripts meant to be copied to your platform's scripts directory (e.g. `~/.hermes/scripts/` or `~/.openclaw/scripts/`). Each shim invokes the installed `coinhunter` CLI:
|
||||||
|
- `coinhunter_precheck_shim.py` — Runs `coinhunter pre`.
|
||||||
|
- `coinhunter_external_gate_shim.py` — Runs `coinhunter gate`.
|
||||||
|
- `coinhunter_review_context_shim.py` — Runs `coinhunter review`.
|
||||||
|
- `rotate_external_gate_log_shim.py` — Runs `coinhunter rotate-log`.
|
||||||
|
|
||||||
|
There is no `pyproject.toml`, `Makefile`, or test suite in this repository.
|
||||||
|
|
||||||
|
## Key architectural concepts
|
||||||
|
|
||||||
|
### Skill vs runtime separation
|
||||||
|
- **Skill code/docs** live in this repository.
|
||||||
|
- **Private user state** lives under `~/.coinhunter/` (positions, balances, logs, reviews, cache, gate state). Never commit user data into this repo.
|
||||||
|
- **Platform cron scripts** are copied from `templates/` to your runtime's scripts directory (e.g. `~/.hermes/scripts/` or `~/.openclaw/scripts/`) and invoke the installed `coinhunter` CLI.
|
||||||
|
|
||||||
|
### Low-cost trigger architecture
|
||||||
|
The framework is designed to minimize LLM invocations:
|
||||||
|
1. A lightweight local Python precheck script decides whether market conditions have changed materially.
|
||||||
|
2. If `should_analyze=false`, the cron job emits `[SILENT]` and exits.
|
||||||
|
3. If `should_analyze=true`, the LLM performs deep analysis and may execute trades.
|
||||||
|
4. An optional external gate (system crontab) can run the precheck every 5 minutes and trigger the Hermes cron only on true events.
|
||||||
|
|
||||||
|
See `SKILL.md` (sections "Low-cost cron architecture" and "Building your own gate") for the full pseudocode, file layout, state schema, and troubleshooting.
|
||||||
|
|
||||||
|
### Trading workflow
|
||||||
|
1. **Portfolio-first rule** — Always read `~/.coinhunter/positions.json`, `accounts.json`, and recent logs before giving trade advice.
|
||||||
|
2. **Scientific checklist** (mandatory before every decision) — trend posture, volume-price fit, key levels, BTC/ETH context, opportunity cost, time window.
|
||||||
|
3. **Execution** — Decide HOLD / SELL_ALL / REBALANCE / BUY. Use `coinhunter exec` for order execution.
|
||||||
|
4. **Review** — Run `coinhunter recap` hourly to analyze decision quality and tune parameters.
|
||||||
|
|
||||||
|
### Production hardening requirements
|
||||||
|
When modifying or adding trading scripts, these safeguards from `SKILL.md` must be respected:
|
||||||
|
- **Idempotency** — every decision carries a `decision_id`; check `~/.coinhunter/executions.json` before submitting orders.
|
||||||
|
- **Exchange reconciliation** — pull real balances before every run; do not trust local state alone.
|
||||||
|
- **Atomic writes** — update `positions.json` and `executions.json` under a file lock with temp-file + rename.
|
||||||
|
- **Order precision validation** — read exchange `lotSize`, `stepSize`, and `minNotional` filters via ccxt before any order.
|
||||||
|
- **Fee buffer** — keep 2%–5% USDT unallocated.
|
||||||
|
- **Structured logging** — write JSONL under `~/.coinhunter/logs/` with `schema_version` and `decision_id`.
|
||||||
|
- **Platform config atomic writes** — if you create or modify `~/.coinhunter/platform.json`, write to a temp file and rename it into place, just like `positions.json` and `executions.json`.
|
||||||
|
|
||||||
|
### Safety rules
|
||||||
|
- No leverage/futures when capital < $200.
|
||||||
|
- When capital < $50, concentrate into **1 position only**.
|
||||||
|
- Blacklist updates should be driven by review findings.
|
||||||
|
|
||||||
|
## Common commands
|
||||||
|
|
||||||
|
- **Install the CLI tool:**
|
||||||
|
```bash
|
||||||
|
pipx install coinhunter
|
||||||
|
# verify
|
||||||
|
coinhunter --version
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Validate a shim after editing:**
|
||||||
|
```bash
|
||||||
|
python3 -m py_compile templates/coinhunter_precheck_shim.py
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Copy shims to your platform's scripts directory:**
|
||||||
|
```bash
|
||||||
|
# Unified shim (recommended)
|
||||||
|
cp templates/coinhunter_shim.py ~/.hermes/scripts/coinhunter_shim.py
|
||||||
|
# or: cp templates/coinhunter_shim.py ~/.openclaw/scripts/coinhunter_shim.py
|
||||||
|
|
||||||
|
# Legacy individual shims (Hermes backward compatibility)
|
||||||
|
cp templates/coinhunter_precheck_shim.py ~/.hermes/scripts/coinhunter_precheck.py
|
||||||
|
cp templates/coinhunter_external_gate_shim.py ~/.hermes/scripts/coinhunter_external_gate.py
|
||||||
|
cp templates/coinhunter_review_context_shim.py ~/.hermes/scripts/coinhunter_review_context.py
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Inspect user state:**
|
||||||
|
```bash
|
||||||
|
cat ~/.coinhunter/positions.json
|
||||||
|
cat ~/.coinhunter/accounts.json
|
||||||
|
ls ~/.coinhunter/logs/
|
||||||
|
ls ~/.coinhunter/reviews/
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Common trading CLI commands:**
|
||||||
|
```bash
|
||||||
|
coinhunter pre
|
||||||
|
coinhunter exec
|
||||||
|
coinhunter recap
|
||||||
|
coinhunter review
|
||||||
|
coinhunter probe bybit-ticker
|
||||||
|
```
|
||||||
|
|
||||||
|
## When making changes
|
||||||
|
|
||||||
|
- If you change `SKILL.md`, check whether `README.md` needs corresponding updates.
|
||||||
|
- If you change shim templates, validate them with `python3 -m py_compile` before copying to your platform's scripts directory.
|
||||||
|
- Keep the separation between this repo and `~/.coinhunter/` — never write personal account data or logs into the skill directory.
|
||||||
106
README.md
106
README.md
@@ -37,29 +37,30 @@
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A[System crontab<br/>every 5 min] -->|local python| B[External Gate]
|
A[System crontab<br/>every 5 min] -->|coinhunter gate| B[External Gate]
|
||||||
B --> C{should_analyze?}
|
B --> C{should_analyze?}
|
||||||
C -->|No| D[Silent exit<br/>zero cost]
|
C -->|No| D[Silent exit<br/>zero cost]
|
||||||
C -->|Yes| E[Trigger Hermes cron]
|
C -->|Yes| E[Trigger platform cron]
|
||||||
E --> F[LLM Deep Analysis]
|
E --> F[LLM Deep Analysis]
|
||||||
F --> G[smart_executor.py]
|
F --> G[coinhunter exec]
|
||||||
G --> H[Binance API]
|
G --> H[Binance API]
|
||||||
F --> I[logger.py]
|
F --> I[coinhunter logs]
|
||||||
I --> J[~/.coinhunter/logs/]
|
I --> J[~/.coinhunter/logs/]
|
||||||
K[review_engine.py<br/>hourly] --> J
|
K[coinhunter recap<br/>hourly] --> J
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key components
|
### Key components
|
||||||
|
|
||||||
| File | Purpose |
|
All operations go through the installed `coinhunter` CLI. This skill provides the framework specification, reference playbooks, and Hermes cron shims.
|
||||||
|------|---------|
|
|
||||||
| `scripts/market_probe.py` | Market data fetcher (ccxt + web search) |
|
| Command | Purpose |
|
||||||
| `scripts/coinhunter_precheck.py` | **Lightweight gate** — computes adaptive thresholds and decides if analysis is needed |
|
|---------|---------|
|
||||||
| `scripts/coinhunter_external_gate.py` | Optional **system-crontab wrapper** that runs the gate entirely outside Hermes |
|
| `coinhunter probe` | Market data fetcher (ccxt + web search) |
|
||||||
| `scripts/coinhunter_cli.py` | Unified CLI entrypoint for CoinHunter operations |
|
| `coinhunter pre` | **Lightweight gate** — computes adaptive thresholds and decides if analysis is needed |
|
||||||
| `scripts/smart_executor.py` | Order execution layer with idempotency & precision validation |
|
| `coinhunter gate` | Optional **system-crontab wrapper** that runs the gate entirely outside Hermes |
|
||||||
| `scripts/logger.py` | Structured JSONL logging of every decision & trade |
|
| `coinhunter exec` | Order execution layer with idempotency & precision validation |
|
||||||
| `scripts/review_engine.py` | Hourly quality review & parameter optimization |
|
| `coinhunter review` | Generate compact review context for the agent |
|
||||||
|
| `coinhunter recap` | Hourly quality review & parameter optimization |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -72,10 +73,21 @@ git clone https://github.com/TacitLab/coinhunter.git
|
|||||||
cd coinhunter
|
cd coinhunter
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Set up your runtime directory
|
### 2. Install the CLI tool
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.coinhunter/state ~/.coinhunter/logs ~/.hermes/scripts
|
pipx install coinhunter
|
||||||
|
# verify
|
||||||
|
coinhunter --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Set up your runtime directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.coinhunter/state ~/.coinhunter/logs
|
||||||
|
# Also create your platform's scripts directory if needed:
|
||||||
|
# mkdir -p ~/.hermes/scripts
|
||||||
|
# mkdir -p ~/.openclaw/scripts
|
||||||
```
|
```
|
||||||
|
|
||||||
Create your initial `positions.json`:
|
Create your initial `positions.json`:
|
||||||
@@ -89,30 +101,64 @@ Create your initial `positions.json`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Build the gate
|
### 4. Deploy the shims
|
||||||
|
|
||||||
Copy the precheck blueprint from [`SKILL.md`](./SKILL.md) into `~/.hermes/scripts/coinhunter_precheck.py`.
|
**Option A — unified shim (recommended for new setups and cross-platform):**
|
||||||
It is ~100 lines of pure Python: reads your state, hashes positions, checks adaptive price/PnL thresholds, and outputs a tiny JSON decision.
|
|
||||||
|
|
||||||
### 4. Configure the Hermes cron job
|
Copy the single unified shim into your platform's scripts directory. It accepts the subcommand as its first argument:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Hermes
|
||||||
|
cp templates/coinhunter_shim.py ~/.hermes/scripts/coinhunter_shim.py
|
||||||
|
|
||||||
|
# OpenClaw
|
||||||
|
cp templates/coinhunter_shim.py ~/.openclaw/scripts/coinhunter_shim.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B — legacy shims (existing Hermes users, unchanged behavior):**
|
||||||
|
|
||||||
|
The original individual shims are still provided for backward compatibility:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp templates/coinhunter_precheck_shim.py ~/.hermes/scripts/coinhunter_precheck.py
|
||||||
|
cp templates/coinhunter_external_gate_shim.py ~/.hermes/scripts/coinhunter_external_gate.py
|
||||||
|
cp templates/coinhunter_review_context_shim.py ~/.hermes/scripts/coinhunter_review_context.py
|
||||||
|
cp templates/rotate_external_gate_log_shim.py ~/.hermes/scripts/rotate_external_gate_log.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Configure the platform cron job
|
||||||
|
|
||||||
|
**Hermes example (using the unified shim):**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"id": "coinhunter-trade",
|
"id": "coinhunter-trade",
|
||||||
"schedule": "*/15 * * * *",
|
"schedule": "*/15 * * * *",
|
||||||
"prompt": "You are Coin Hunter. If injected context says should_analyze=false, respond with exactly [SILENT]. Otherwise read positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute.",
|
"prompt": "You are Coin Hunter. If injected context says should_analyze=false, respond with exactly [SILENT]. Otherwise read positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute.",
|
||||||
"script": "~/.hermes/scripts/coinhunter_precheck.py",
|
"script": "coinhunter_shim.py pre",
|
||||||
"deliver": "telegram",
|
"deliver": "telegram",
|
||||||
"model": "kimi-for-coding"
|
"model": "kimi-for-coding"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. (Optional) Add the external gate
|
**OpenClaw example:**
|
||||||
|
|
||||||
Put this in your system crontab to run the precheck every **5 minutes** without ever waking the LLM:
|
```json
|
||||||
|
{
|
||||||
|
"id": "coinhunter-trade",
|
||||||
|
"schedule": "*/15 * * * *",
|
||||||
|
"prompt": "You are Coin Hunter. If injected context says should_analyze=false, respond with exactly [SILENT]. Otherwise read positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute.",
|
||||||
|
"script": "coinhunter_shim.py pre",
|
||||||
|
"deliver": "webhook"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. (Optional) Add the external gate
|
||||||
|
|
||||||
|
Put this in your system crontab to run the gate every **5 minutes** without ever waking the LLM:
|
||||||
|
|
||||||
```cron
|
```cron
|
||||||
*/5 * * * * /usr/bin/python3 /home/user/.hermes/scripts/coinhunter_external_gate.py >> /home/user/.coinhunter/logs/external_gate.log 2>&1
|
*/5 * * * * /usr/bin/env coinhunter gate >> /home/user/.coinhunter/logs/external_gate.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -160,11 +206,13 @@ See the full step-by-step gate blueprint in [`SKILL.md`](./SKILL.md).
|
|||||||
coinhunter/
|
coinhunter/
|
||||||
├── README.md # You are here
|
├── README.md # You are here
|
||||||
├── SKILL.md # Full framework spec + gate blueprint
|
├── SKILL.md # Full framework spec + gate blueprint
|
||||||
├── scripts/
|
├── CLAUDE.md # Guidance for Claude Code
|
||||||
│ ├── market_probe.py # Market data fetcher
|
├── templates/ # Platform cron shims (call the installed coinhunter CLI)
|
||||||
│ ├── init_user_state.py # Bootstrap helper
|
│ ├── coinhunter_shim.py # Unified cross-platform shim (recommended)
|
||||||
│ ├── auto_trader.py # Reference trading loop
|
│ ├── coinhunter_precheck_shim.py
|
||||||
│ └── ... # Your gate scripts live in ~/.hermes/scripts/
|
│ ├── coinhunter_external_gate_shim.py
|
||||||
|
│ ├── coinhunter_review_context_shim.py
|
||||||
|
│ └── rotate_external_gate_log_shim.py
|
||||||
└── references/
|
└── references/
|
||||||
├── short-term-trading-framework.md
|
├── short-term-trading-framework.md
|
||||||
├── review-template.md
|
├── review-template.md
|
||||||
|
|||||||
82
SKILL.md
82
SKILL.md
@@ -76,6 +76,12 @@ Read `references/short-term-trading-framework.md` before every active decision p
|
|||||||
|
|
||||||
## Auto-trading architecture
|
## Auto-trading architecture
|
||||||
|
|
||||||
|
Install the executable CLI first:
|
||||||
|
```bash
|
||||||
|
pipx install coinhunter
|
||||||
|
# or: pip install coinhunter
|
||||||
|
```
|
||||||
|
|
||||||
| CLI Command | Purpose |
|
| CLI Command | Purpose |
|
||||||
|-------------|---------|
|
|-------------|---------|
|
||||||
| `coinhunter exec` | Order execution layer (buy / flat / rotate / hold) |
|
| `coinhunter exec` | Order execution layer (buy / flat / rotate / hold) |
|
||||||
@@ -92,7 +98,7 @@ Read `references/short-term-trading-framework.md` before every active decision p
|
|||||||
When model cost or quota is tight, do not let every cron run perform full analysis from scratch.
|
When model cost or quota is tight, do not let every cron run perform full analysis from scratch.
|
||||||
|
|
||||||
Recommended pattern:
|
Recommended pattern:
|
||||||
1. Attach a lightweight Python `script` to the cron job (under `~/.hermes/scripts/`) that fetches balances/tickers, computes hashes, and emits compact JSON context.
|
1. Attach a lightweight Python `script` to the cron job (under your platform's scripts directory, e.g. `~/.hermes/scripts/` or `~/.openclaw/scripts/`) that fetches balances/tickers, computes hashes, and emits compact JSON context.
|
||||||
2. Cache the last observed positions, top candidates, market regime, and `last_deep_analysis_at` under `~/.coinhunter/state/`.
|
2. Cache the last observed positions, top candidates, market regime, and `last_deep_analysis_at` under `~/.coinhunter/state/`.
|
||||||
3. Trigger full analysis only when one of these changes materially. Make the thresholds adaptive instead of fixed:
|
3. Trigger full analysis only when one of these changes materially. Make the thresholds adaptive instead of fixed:
|
||||||
- position structure changes (hard trigger)
|
- position structure changes (hard trigger)
|
||||||
@@ -105,10 +111,10 @@ Recommended pattern:
|
|||||||
7. For even lower spend, move the high-frequency cadence outside Hermes cron entirely:
|
7. For even lower spend, move the high-frequency cadence outside Hermes cron entirely:
|
||||||
- install a system `crontab` entry that runs a local gate script every 5-10 minutes
|
- install a system `crontab` entry that runs a local gate script every 5-10 minutes
|
||||||
- let that gate script run the lightweight precheck
|
- let that gate script run the lightweight precheck
|
||||||
- only when `should_analyze=true` and no run is already queued, trigger the Hermes cron job via `hermes cron run <job_id>`
|
- only when `should_analyze=true` and no run is already queued, trigger your platform's cron job (e.g. `hermes cron run <job_id>` or `openclaw trigger <job_id>`)
|
||||||
- store a `run_requested_at` marker in `~/.coinhunter/state/precheck_state.json` and clear it when the analysis acknowledges completion
|
- store a `run_requested_at` marker in `~/.coinhunter/state/precheck_state.json` and clear it when the analysis acknowledges completion
|
||||||
|
|
||||||
This pattern preserves Telegram auto-delivery from Hermes cron while reducing model wakeups to trigger-only events.
|
This pattern preserves auto-delivery from your platform's cron system while reducing model wakeups to trigger-only events.
|
||||||
|
|
||||||
### Practical production notes for external gate mode
|
### Practical production notes for external gate mode
|
||||||
- Put the external gate itself on system `crontab` (for example every 5 minutes) rather than on Hermes cron. That keeps the high-frequency loop completely local and model-free.
|
- Put the external gate itself on system `crontab` (for example every 5 minutes) rather than on Hermes cron. That keeps the high-frequency loop completely local and model-free.
|
||||||
@@ -214,31 +220,51 @@ if __name__ == "__main__":
|
|||||||
print(json.dumps(result))
|
print(json.dumps(result))
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4. Hermes cron job configuration
|
#### 4. Cron job configuration
|
||||||
Attach the precheck script as the `script` field of the cron job so its JSON output is injected into the prompt:
|
Attach the precheck script as the `script` field of the cron job so its JSON output is injected into the prompt.
|
||||||
|
|
||||||
|
**Hermes example:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"id": "coinhunter-trade",
|
"id": "coinhunter-trade",
|
||||||
"schedule": "*/15 * * * *",
|
"schedule": "*/15 * * * *",
|
||||||
"prompt": "You are Coin Hunter. If the injected context says should_analyze=false, respond with exactly [SILENT] and do nothing. Otherwise, read ~/.coinhunter/positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute via the `coinhunter` CLI. After finishing, run `coinhunter pre --ack` to clear the trigger.",
|
"prompt": "You are Coin Hunter. If the injected context says should_analyze=false, respond with exactly [SILENT] and do nothing. Otherwise, read ~/.coinhunter/positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute via the `coinhunter` CLI. After finishing, run `coinhunter pre --ack` to clear the trigger.",
|
||||||
"script": "coinhunter_precheck.py",
|
"script": "coinhunter_shim.py pre",
|
||||||
"deliver": "telegram",
|
"deliver": "telegram",
|
||||||
"model": "kimi-for-coding"
|
"model": "kimi-for-coding"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Add an `--ack` handler to the precheck script (or a separate ack script) that sets `run_acknowledged_at` and clears `run_requested_at` so the gate does not re-fire until the next true trigger.
|
**OpenClaw example:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "coinhunter-trade",
|
||||||
|
"schedule": "*/15 * * * *",
|
||||||
|
"prompt": "You are Coin Hunter. If the injected context says should_analyze=false, respond with exactly [SILENT] and do nothing. Otherwise, read ~/.coinhunter/positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute via the `coinhunter` CLI. After finishing, run `coinhunter pre --ack` to clear the trigger.",
|
||||||
|
"script": "coinhunter_shim.py pre",
|
||||||
|
"deliver": "webhook"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Acknowledge completion by running `coinhunter pre --ack` so the gate clears `run_requested_at` and does not re-fire until the next true trigger.
|
||||||
|
|
||||||
#### 5. External gate (optional, for even lower cost)
|
#### 5. External gate (optional, for even lower cost)
|
||||||
If you want to run the precheck every 5 minutes without waking Hermes at all:
|
If you want to run the precheck every 5 minutes without waking Hermes at all:
|
||||||
|
|
||||||
External gate pseudocode (run from `~/.hermes/scripts/`):
|
External gate pseudocode (run from your platform's scripts directory):
|
||||||
```python
|
```python
|
||||||
import fcntl, os, subprocess, json, sys
|
import fcntl, os, subprocess, json, sys
|
||||||
|
|
||||||
LOCK_PATH = os.path.expanduser("~/.coinhunter/state/external_gate.lock")
|
LOCK_PATH = os.path.expanduser("~/.coinhunter/state/external_gate.lock")
|
||||||
PRECHECK = os.path.expanduser("~/.hermes/scripts/coinhunter_precheck.py")
|
|
||||||
JOB_ID = "coinhunter-trade"
|
JOB_ID = "coinhunter-trade"
|
||||||
|
PLATFORM_PATH = os.path.expanduser("~/.coinhunter/platform.json")
|
||||||
|
|
||||||
|
# Load platform config if it exists; default to Hermes behavior
|
||||||
|
platform = {"cron_command": ["hermes", "cron", "run"]}
|
||||||
|
if os.path.exists(PLATFORM_PATH):
|
||||||
|
platform.update(json.load(open(PLATFORM_PATH)))
|
||||||
|
|
||||||
|
cron_command = platform.get("cron_command", ["hermes", "cron", "run"])
|
||||||
|
|
||||||
with open(LOCK_PATH, "w") as f:
|
with open(LOCK_PATH, "w") as f:
|
||||||
try:
|
try:
|
||||||
@@ -246,22 +272,37 @@ with open(LOCK_PATH, "w") as f:
|
|||||||
except BlockingIOError:
|
except BlockingIOError:
|
||||||
sys.exit(0) # another instance is running
|
sys.exit(0) # another instance is running
|
||||||
|
|
||||||
result = json.loads(os.popen(f"python {PRECHECK}").read())
|
result = json.loads(os.popen("coinhunter pre").read())
|
||||||
if result.get("should_analyze"):
|
if result.get("should_analyze"):
|
||||||
# Trigger Hermes cron only if not already requested
|
# Trigger platform cron only if not already requested
|
||||||
state_path = os.path.expanduser("~/.coinhunter/state/precheck_state.json")
|
state_path = os.path.expanduser("~/.coinhunter/state/precheck_state.json")
|
||||||
state = json.load(open(state_path))
|
state = json.load(open(state_path))
|
||||||
if not state.get("run_requested_at"):
|
if not state.get("run_requested_at"):
|
||||||
subprocess.run(["hermes", "cron", "run", JOB_ID], check=False)
|
subprocess.run([*cron_command, JOB_ID], check=False)
|
||||||
```
|
```
|
||||||
|
|
||||||
System crontab entry:
|
System crontab entry:
|
||||||
```cron
|
```cron
|
||||||
*/5 * * * * /usr/bin/python3 /home/user/.hermes/scripts/coinhunter_external_gate.py >> /home/user/.coinhunter/logs/external_gate.log 2>&1
|
*/5 * * * * /usr/bin/env coinhunter gate >> /home/user/.coinhunter/logs/external_gate.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
With this setup, the model is only invoked when a material market change occurs—preserving intelligence while cutting routine cost by 80-95%.
|
With this setup, the model is only invoked when a material market change occurs—preserving intelligence while cutting routine cost by 80-95%.
|
||||||
|
|
||||||
|
### Troubleshooting common precheck errors
|
||||||
|
When `coinhunter pre` fails with `status: deep_analysis_required` and `reasons: ["precheck-error"]`, inspect the `details` field and apply these known fixes:
|
||||||
|
|
||||||
|
1. **`'PosixPath' object has no attribute 'env_file'`**
|
||||||
|
- Location: inside the installed `coinhunter` package (`src/coinhunter/services/market_data.py` in the PyPI source)
|
||||||
|
- Cause: `load_env_file(ENV_FILE)` is passed a `Path` object, but `load_env_file()` expects either a `RuntimePaths` dataclass or no arguments.
|
||||||
|
- Fix: Update `coinhunter` to the latest version from PyPI. If the bug persists, patch the installed package and submit an issue to the `coinhunter` project.
|
||||||
|
|
||||||
|
2. **`name 'BASE_PN_L_TRIGGER_PCT' is not defined`**
|
||||||
|
- Location: inside the installed `coinhunter` package (`src/coinhunter/services/adaptive_profile.py` in the PyPI source)
|
||||||
|
- Cause: Typo `BASE_PN_L_TRIGGER_PCT` instead of `BASE_PNL_TRIGGER_PCT`.
|
||||||
|
- Fix: Update `coinhunter` to the latest version from PyPI. If the bug persists, patch the installed package and submit an issue to the `coinhunter` project.
|
||||||
|
|
||||||
|
After updating, rerun `coinhunter pre` to verify the gate clears before executing the trading decision.
|
||||||
|
|
||||||
### Production hardening (mandatory)
|
### Production hardening (mandatory)
|
||||||
The live trading stack must include these safeguards:
|
The live trading stack must include these safeguards:
|
||||||
1. **Idempotency** — every decision carries a `decision_id`. The executor checks `~/.coinhunter/executions.json` before submitting orders to prevent duplicate trades.
|
1. **Idempotency** — every decision carries a `decision_id`. The executor checks `~/.coinhunter/executions.json` before submitting orders to prevent duplicate trades.
|
||||||
@@ -272,6 +313,21 @@ The live trading stack must include these safeguards:
|
|||||||
6. **Structured logging** — every decision, trade, error, and balance snapshot is written as JSONL under `~/.coinhunter/logs/` with `schema_version` and `decision_id`.
|
6. **Structured logging** — every decision, trade, error, and balance snapshot is written as JSONL under `~/.coinhunter/logs/` with `schema_version` and `decision_id`.
|
||||||
7. **Error logging** — failed API calls, rejected orders, and reconciliation mismatches are captured in `logs/errors_YYYYMMDD.jsonl` and fed into the hourly review.
|
7. **Error logging** — failed API calls, rejected orders, and reconciliation mismatches are captured in `logs/errors_YYYYMMDD.jsonl` and fed into the hourly review.
|
||||||
|
|
||||||
|
## Cross-platform deployment
|
||||||
|
|
||||||
|
Coin Hunter is runtime-agnostic. It works on Hermes, OpenClaw, and any compatible cron-based platform.
|
||||||
|
|
||||||
|
1. **Install the CLI** (same everywhere):
|
||||||
|
```bash
|
||||||
|
pipx install coinhunter
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Place the shim** in your platform's scripts directory:
|
||||||
|
- Hermes: `~/.hermes/scripts/coinhunter_shim.py`
|
||||||
|
- OpenClaw: `~/.openclaw/scripts/coinhunter_shim.py`
|
||||||
|
|
||||||
|
3. *(Optional)* Create `~/.coinhunter/platform.json` if you want the external gate to use a non-default trigger command. When absent, the gate falls back to Hermes behavior (`hermes cron run`).
|
||||||
|
|
||||||
## Safety rules
|
## Safety rules
|
||||||
- No leverage/futures when capital < $200.
|
- No leverage/futures when capital < $200.
|
||||||
- When capital < $50, concentrate into **1 position only**.
|
- When capital < $50, concentrate into **1 position only**.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Complete guide for building and running a hands-off meme-coin trading bot using the Binance Spot API.
|
Complete guide for building and running a hands-off meme-coin trading bot using the Binance Spot API.
|
||||||
|
|
||||||
> Note: CoinHunter code now lives in `~/.hermes/skills/coinhunter/scripts/` and is preferably invoked via `coinhunter_cli.py`. Treat any references in this guide to runtime copies under `~/.coinhunter/` or shell wrappers like `run_trader.sh` as legacy structure notes unless explicitly updated below.
|
> Note: The CoinHunter CLI is an external PyPI package (`pipx install coinhunter`). All execution goes through the `coinhunter` command. Treat any references in this guide to local source directories, `coinhunter_cli.py`, or shell wrappers like `run_trader.sh` as legacy structure notes unless explicitly updated below.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
@@ -23,13 +23,15 @@ This guide covers:
|
|||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
|
> **Note:** The current architecture uses the external `coinhunter` CLI (installed from PyPI) plus thin platform shims. The legacy local files (`auto_trader.py`, `run_trader.sh`) noted below are historical references only.
|
||||||
|
|
||||||
```
|
```
|
||||||
~/.coinhunter/
|
~/.coinhunter/
|
||||||
├── auto_trader.py # Main trading logic
|
├── .env # API keys and secrets
|
||||||
├── run_trader.sh # Shell wrapper (venv + env vars + logging)
|
├── positions.json # Portfolio state (shared with coinhunter)
|
||||||
├── check_api.py # Quick API connectivity validator
|
├── state/ # Gate state and locks
|
||||||
├── logs/trader.log # Execution logs
|
├── logs/ # Execution logs
|
||||||
└── positions.json # Portfolio state (shared with coinhunter)
|
└── reviews/ # Hourly review reports
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 1: Binance API Key setup
|
## Step 1: Binance API Key setup
|
||||||
@@ -44,15 +46,17 @@ This guide covers:
|
|||||||
- Use the public IP of the machine that will run the bot
|
- Use the public IP of the machine that will run the bot
|
||||||
- This prevents key reuse if the credential is ever leaked
|
- This prevents key reuse if the credential is ever leaked
|
||||||
|
|
||||||
**Security reminder:** never paste API keys into chat messages. Write them directly into `~/.hermes/.env`.
|
**Security reminder:** never paste API keys into chat messages. Write them into your platform's environment file (e.g. `~/.hermes/.env` or `~/.openclaw/.env`). You can also store them under `~/.coinhunter/.env` and source that file in your wrapper script.
|
||||||
|
|
||||||
## Step 2: Store credentials
|
## Step 2: Store credentials
|
||||||
|
|
||||||
Append to `~/.hermes/.env`:
|
Append to your environment file (check `platform.json` -> `env_file` if you have one, otherwise use your platform default):
|
||||||
|
|
||||||
```env
|
```bash
|
||||||
|
cat >> ~/.coinhunter/.env << 'EOF'
|
||||||
BINANCE_API_KEY=your_api_key_here
|
BINANCE_API_KEY=your_api_key_here
|
||||||
BINANCE_API_SECRET=your_api_secret_here
|
BINANCE_API_SECRET=your_api_secret_here
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 3: Install dependencies
|
## Step 3: Install dependencies
|
||||||
@@ -72,46 +76,33 @@ pip install ccxt pandas numpy
|
|||||||
|
|
||||||
## Step 4: Deploy the bot
|
## Step 4: Deploy the bot
|
||||||
|
|
||||||
Use `scripts/auto_trader.py` from the coinhunter skill as the template. Copy it into the user's `~/.coinhunter/` directory and customize:
|
The trading logic is provided by the external `coinhunter` CLI. To run it automatically, deploy the platform shim and a small wrapper script.
|
||||||
|
|
||||||
- `MAX_POSITIONS` — max concurrent meme-coin positions (default 2)
|
If you need custom parameters (max positions, allocation percentage, stop-loss levels), configure them in `~/.coinhunter/config.json` and reference them from your wrapper script, or pass them as flags to `coinhunter exec`.
|
||||||
- `CAPITAL_ALLOCATION_PCT` — fraction of total USDT to use (default 0.95; leave ~5% buffer for fees/slippage)
|
|
||||||
- `MIN_POSITION_USDT` — minimum single order size (default 50)
|
|
||||||
- `STOP_LOSS_PCT` / `TAKE_PROFIT_1_PCT` / `TAKE_PROFIT_2_PCT` — risk levels
|
|
||||||
|
|
||||||
Create `run_trader.sh`:
|
Example wrapper (`run_trader.sh`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
python3 check_api.py
|
source ~/.coinhunter/.env
|
||||||
source /path/to/venv/bin/activate
|
source /path/to/venv/bin/activate
|
||||||
export DRY_RUN=${DRY_RUN:-true}
|
export DRY_RUN=${DRY_RUN:-true}
|
||||||
python3 auto_trader.py >> logs/trader.log 2>&1
|
coinhunter exec >> logs/trader.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
Make executable:
|
Make executable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x run_trader.sh check_api.py
|
chmod +x run_trader.sh
|
||||||
mkdir -p logs
|
mkdir -p logs
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 5: Validate API connectivity
|
## Step 5: Run a DRY_RUN test
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 check_api.py
|
DRY_RUN=true coinhunter exec
|
||||||
```
|
|
||||||
|
|
||||||
Expected output: `✅ API 配置正常`
|
|
||||||
|
|
||||||
If this fails, the bot will exit immediately on each run.
|
|
||||||
|
|
||||||
## Step 6: Run a DRY_RUN test
|
|
||||||
|
|
||||||
```bash
|
|
||||||
DRY_RUN=true python3 auto_trader.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected behavior:
|
Expected behavior:
|
||||||
@@ -123,9 +114,9 @@ Expected behavior:
|
|||||||
|
|
||||||
Only proceed to live trading after at least one dry-run cycle completes without errors.
|
Only proceed to live trading after at least one dry-run cycle completes without errors.
|
||||||
|
|
||||||
## Step 7: Schedule with cronjob
|
## Step 6: Schedule with your platform's cron system
|
||||||
|
|
||||||
Use the `cronjob` tool to run the bot every 15 minutes:
|
**Hermes example:**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -137,7 +128,19 @@ Use the `cronjob` tool to run the bot every 15 minutes:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 8: Switch to live trading
|
**OpenClaw example:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "create",
|
||||||
|
"name": "Coin Hunter Auto Trader",
|
||||||
|
"schedule": "*/15 * * * *",
|
||||||
|
"deliver": "webhook",
|
||||||
|
"prompt": "Run the Coin Hunter automatic meme-coin trading bot.\n1. cd /home/<user>/.coinhunter\n2. ./run_trader.sh\n3. Summarize actions and report back."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 7: Switch to live trading
|
||||||
|
|
||||||
Once DRY_RUN validation succeeds and the user confirms:
|
Once DRY_RUN validation succeeds and the user confirms:
|
||||||
|
|
||||||
@@ -151,7 +154,7 @@ Once DRY_RUN validation succeeds and the user confirms:
|
|||||||
|
|
||||||
1. **Never enable Withdrawal permission** on the API key.
|
1. **Never enable Withdrawal permission** on the API key.
|
||||||
2. **Always bind an IP whitelist** if possible.
|
2. **Always bind an IP whitelist** if possible.
|
||||||
3. **Never accept API keys in plaintext chat.** Ask the user to write them into `~/.hermes/.env`.
|
3. **Never accept API keys in plaintext chat.** Ask the user to write them into their platform environment file (e.g. `~/.hermes/.env` or `~/.openclaw/.env`) or `~/.coinhunter/.env`.
|
||||||
4. **Do not set allocation to exactly 100%.** Leave at least 3–5% buffer for fees and slippage.
|
4. **Do not set allocation to exactly 100%.** Leave at least 3–5% buffer for fees and slippage.
|
||||||
5. **Start with DRY_RUN.** Run at least one full cycle before going live.
|
5. **Start with DRY_RUN.** Run at least one full cycle before going live.
|
||||||
6. **Check the account balance first.** If USDT is 0 (or held in Earn/Margin/Futures), the bot cannot trade.
|
6. **Check the account balance first.** If USDT is 0 (or held in Earn/Margin/Futures), the bot cannot trade.
|
||||||
@@ -172,10 +175,10 @@ ticker = tickers.get(sym_ccxt)
|
|||||||
|
|
||||||
### .env file is protected
|
### .env file is protected
|
||||||
|
|
||||||
The `patch` tool may reject edits to `~/.hermes/.env`. Use terminal redirection instead:
|
The `patch` tool may reject edits to environment files. Use terminal redirection instead:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat >> ~/.hermes/.env << 'EOF'
|
cat >> ~/.coinhunter/.env << 'EOF'
|
||||||
BINANCE_API_KEY=xxx
|
BINANCE_API_KEY=xxx
|
||||||
BINANCE_API_SECRET=yyy
|
BINANCE_API_SECRET=yyy
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -1,16 +1,33 @@
|
|||||||
# CoinHunter shim templates
|
# CoinHunter shim templates
|
||||||
|
|
||||||
These files are tiny compatibility shims for Hermes platform features that currently expect scripts under `~/.hermes/scripts/`.
|
These files are tiny compatibility shims for cron-based platforms (Hermes, OpenClaw, etc.) that expect scripts under a scripts directory such as `~/.hermes/scripts/` or `~/.openclaw/scripts/`.
|
||||||
|
|
||||||
When needed, copy them like this:
|
## Unified shim (recommended)
|
||||||
|
|
||||||
|
`templates/coinhunter_shim.py` is the cross-platform wrapper. It takes the subcommand as its first argument and delegates to the installed `coinhunter` CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp templates/coinhunter_shim.py ~/.hermes/scripts/coinhunter_shim.py
|
||||||
|
# or
|
||||||
|
cp templates/coinhunter_shim.py ~/.openclaw/scripts/coinhunter_shim.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage examples:
|
||||||
|
- `coinhunter_shim.py pre`
|
||||||
|
- `coinhunter_shim.py gate`
|
||||||
|
- `coinhunter_shim.py review`
|
||||||
|
- `coinhunter_shim.py rotate-log`
|
||||||
|
|
||||||
|
## Legacy shims (backward compatibility)
|
||||||
|
|
||||||
|
The original individual shims are still provided for existing Hermes users who already have them deployed. Their behavior is unchanged:
|
||||||
|
|
||||||
- `templates/coinhunter_precheck_shim.py` -> `~/.hermes/scripts/coinhunter_precheck.py`
|
- `templates/coinhunter_precheck_shim.py` -> `~/.hermes/scripts/coinhunter_precheck.py`
|
||||||
- `templates/coinhunter_external_gate_shim.py` -> `~/.hermes/scripts/coinhunter_external_gate.py`
|
- `templates/coinhunter_external_gate_shim.py` -> `~/.hermes/scripts/coinhunter_external_gate.py`
|
||||||
- `templates/coinhunter_review_context_shim.py` -> `~/.hermes/scripts/coinhunter_review_context.py`
|
- `templates/coinhunter_review_context_shim.py` -> `~/.hermes/scripts/coinhunter_review_context.py`
|
||||||
- `templates/rotate_external_gate_log_shim.sh` -> `~/.hermes/scripts/rotate_external_gate_log.sh`
|
- `templates/rotate_external_gate_log_shim.py` -> `~/.hermes/scripts/rotate_external_gate_log.py`
|
||||||
|
|
||||||
The real business logic stays inside the skill under:
|
The real business logic lives in the external `coinhunter` CLI package (installed from PyPI). These shims only delegate to it.
|
||||||
- `~/.hermes/skills/coinhunter/scripts/`
|
|
||||||
|
|
||||||
The user runtime data stays under:
|
The user runtime data stays under:
|
||||||
- `~/.coinhunter/`
|
- `~/.coinhunter/`
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ This keeps personal accounts, positions, and watchlists out of packaged skill ar
|
|||||||
```text
|
```text
|
||||||
~/.coinhunter/
|
~/.coinhunter/
|
||||||
├── config.json
|
├── config.json
|
||||||
|
├── platform.json
|
||||||
├── accounts.json
|
├── accounts.json
|
||||||
├── positions.json
|
├── positions.json
|
||||||
├── watchlist.json
|
├── watchlist.json
|
||||||
@@ -46,6 +47,28 @@ Example:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### platform.json
|
||||||
|
Optional cross-platform runtime configuration. When absent, the framework defaults to Hermes behavior.
|
||||||
|
|
||||||
|
Suggested fields:
|
||||||
|
- `platform` — runtime name (`"hermes"` or `"openclaw"`)
|
||||||
|
- `scripts_dir` — where platform shims are deployed
|
||||||
|
- `env_file` — path to the environment file for secrets
|
||||||
|
- `cron_command` — command array used by the external gate to trigger a job
|
||||||
|
- `delivery` — default delivery channel (`"telegram"`, `"webhook"`, etc.)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"platform": "openclaw",
|
||||||
|
"scripts_dir": "~/.openclaw/scripts",
|
||||||
|
"env_file": "~/.openclaw/.env",
|
||||||
|
"cron_command": ["openclaw", "trigger"],
|
||||||
|
"delivery": "webhook"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### accounts.json
|
### accounts.json
|
||||||
Store exchange accounts and balances.
|
Store exchange accounts and balances.
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Compatibility shim for external gate execution.
|
"""Hermes cron shim: runs coinhunter external-gate via CLI."""
|
||||||
Real logic lives in the CoinHunter skill.
|
import shutil
|
||||||
Copy this file to ~/.hermes/scripts/coinhunter_external_gate.py if needed.
|
import subprocess
|
||||||
"""
|
import sys
|
||||||
import runpy
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
TARGET = Path.home() / ".hermes" / "skills" / "coinhunter" / "scripts" / "coinhunter_external_gate.py"
|
BIN = shutil.which("coinhunter") or shutil.which("coinhunter.exe")
|
||||||
runpy.run_path(str(TARGET), run_name="__main__")
|
if not BIN:
|
||||||
|
print("error: coinhunter CLI not found in PATH. Install with: pipx install coinhunter", file=sys.stderr)
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([BIN, "gate", *sys.argv[1:]]).returncode)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Compatibility shim for Hermes cron script hook.
|
"""Hermes cron shim: runs coinhunter precheck via CLI."""
|
||||||
Real logic lives in the CoinHunter skill.
|
import shutil
|
||||||
Copy this file to ~/.hermes/scripts/coinhunter_precheck.py if needed.
|
import subprocess
|
||||||
"""
|
import sys
|
||||||
import runpy
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
TARGET = Path.home() / ".hermes" / "skills" / "coinhunter" / "scripts" / "coinhunter_precheck.py"
|
BIN = shutil.which("coinhunter") or shutil.which("coinhunter.exe")
|
||||||
runpy.run_path(str(TARGET), run_name="__main__")
|
if not BIN:
|
||||||
|
print("error: coinhunter CLI not found in PATH. Install with: pipx install coinhunter", file=sys.stderr)
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([BIN, "pre", *sys.argv[1:]]).returncode)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Compatibility shim for review-context cron script hook.
|
"""Hermes cron shim: runs coinhunter review-context via CLI."""
|
||||||
Real logic lives in the CoinHunter skill.
|
import shutil
|
||||||
Copy this file to ~/.hermes/scripts/coinhunter_review_context.py if needed.
|
import subprocess
|
||||||
"""
|
import sys
|
||||||
import runpy
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
TARGET = Path.home() / ".hermes" / "skills" / "coinhunter" / "scripts" / "coinhunter_review_context.py"
|
BIN = shutil.which("coinhunter") or shutil.which("coinhunter.exe")
|
||||||
runpy.run_path(str(TARGET), run_name="__main__")
|
if not BIN:
|
||||||
|
print("error: coinhunter CLI not found in PATH. Install with: pipx install coinhunter", file=sys.stderr)
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([BIN, "review", *sys.argv[1:]]).returncode)
|
||||||
|
|||||||
23
templates/coinhunter_shim.py
Normal file
23
templates/coinhunter_shim.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Cross-platform cron shim: delegates any coinhunter subcommand via CLI."""
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
BIN = shutil.which("coinhunter") or shutil.which("coinhunter.exe")
|
||||||
|
if not BIN:
|
||||||
|
print(
|
||||||
|
"error: coinhunter CLI not found in PATH. Install with: pipx install coinhunter",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("usage: coinhunter_shim.py <subcommand> [args...]", file=sys.stderr)
|
||||||
|
print("example: coinhunter_shim.py pre", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
subcommand = sys.argv[1]
|
||||||
|
args = sys.argv[2:]
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([BIN, subcommand, *args]).returncode)
|
||||||
12
templates/rotate_external_gate_log_shim.py
Normal file
12
templates/rotate_external_gate_log_shim.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Hermes cron shim: runs coinhunter rotate-log via CLI."""
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
BIN = shutil.which("coinhunter") or shutil.which("coinhunter.exe")
|
||||||
|
if not BIN:
|
||||||
|
print("error: coinhunter CLI not found in PATH. Install with: pipx install coinhunter", file=sys.stderr)
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
sys.exit(subprocess.run([BIN, "rotate-log", *sys.argv[1:]]).returncode)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
python3 "$HOME/.hermes/skills/coinhunter/scripts/rotate_external_gate_log.py"
|
|
||||||
Reference in New Issue
Block a user