Autonomous Meteora DLMM liquidity management agent for Solana.
Meridian screens pools, deploys capital, manages open positions, records lessons, and can evolve both thresholds and prompt behavior over time. It is designed to run continuously with a web dashboard, REPL, and optional Telegram control surface.
Meridian has three LLM-facing agent roles:
| Agent | Purpose | Typical schedule |
|---|---|---|
SCREENER |
Finds candidates, studies pools, decides whether to deploy | every screeningIntervalMin |
MANAGER |
Reviews live positions, claims fees, closes or holds | every managementIntervalMin |
GENERAL |
Chat and command handling | on demand |
There is also an autoresearch subsystem that tests prompt changes after real closes and keeps or reverts them based on later performance.
Meridian supports five provider modes. Set via LLM_PROVIDER in .env or llmProvider in user-config.json:
| Provider | How it works | Auth | Cost |
|---|---|---|---|
claude |
Runs model turns through claude -p (Claude Code CLI) |
OAuth login (claude CLI) |
Uses your Claude Pro/Max subscription |
codex |
Runs model turns through codex exec (Codex CLI) |
OAuth login (codex login) |
Uses your Codex/OpenAI subscription |
openrouter |
Direct HTTP API calls to any model | OPENROUTER_API_KEY |
Pay-per-token via OpenRouter |
deepseek |
Direct HTTP API calls | DEEPSEEK_API_KEY |
Pay-per-token via DeepSeek |
minimax |
Direct HTTP API calls to MiniMax's OpenAI-compatible API | MINIMAX_API_KEY |
Uses your MiniMax Token Plan or pay-as-you-go key |
Uses claude -p (Claude Code print mode) with your existing Claude subscription. No API key billing — runs on your OAuth login. Supports per-role model selection:
{
"llmProvider": "claude",
"screeningModel": "opus",
"managementModel": "haiku",
"generalModel": "sonnet",
"autoresearchModel": "opus"
}Available model aliases: opus (Opus 4.6), sonnet (Sonnet 4.6), haiku (Haiku 4.5).
Uses codex exec with your OpenAI/Codex subscription. Same CLI harness pattern as Claude but with OpenAI models.
Uses the OpenRouter API to access any model (minimax, qwen, etc.). Requires OPENROUTER_API_KEY in .env. Good for cheap models like minimax/minimax-m2.7 or free models like qwen/qwen3.6-plus:free.
Uses MiniMax's OpenAI-compatible API directly at https://api.minimax.io/v1. This is the right option if you want to use a MiniMax Token Plan key directly instead of routing MiniMax through OpenRouter.
Typical models:
MiniMax-M2.7MiniMax-M2.7-highspeedMiniMax-M2.5
All providers use the same ReAct loop with your custom tools — the provider only affects which LLM processes the prompts.
LLM provider -> ReAct loop -> tools -> Meteora / Helius / Jupiter / LP Agent
| |
| +-- wallet, pools, token info, deploy, close, swap
|
+-- Screener
+-- Manager
+-- General chat
+-- Autoresearch prompt optimizer
- Node.js 18+
- A Solana wallet private key in base58 format
- A Solana RPC URL, ideally Helius
- Codex CLI login if using
codex - LP Agent API key if you want LP overview / top LPer study
- Telegram bot token if you want Telegram control and notifications
git clone https://github.com/fciaf420/meridian.git
cd meridian
npm install
cd web && npm install && npm run build && cd ..Nuggets (holographic memory) is bundled in packages/nuggets/ — no separate repo needed.
Choose your provider:
Claude (recommended — uses your Claude subscription):
# Make sure claude CLI is installed and logged in
claude --versionCodex (uses your OpenAI/Codex subscription):
codex loginOpenRouter (pay-per-token, any model):
Add OPENROUTER_API_KEY=sk-or-... to .env
MiniMax Token Plan (direct MiniMax access):
Add MINIMAX_API_KEY=... to .env
Then run:
npm run setupThe setup wizard saves a starter user-config.json. It asks for:
- wallet and RPC
- risk preset
- deploy size and limits
- screening and management cadence
- provider selection
- a default model ID
- dry-run vs live mode
Before live trading:
npm run devThis runs the full bot with DRY_RUN=true. The agent still screens, manages, chats, updates the dashboard, and runs cron jobs, but real transactions are not broadcast.
When you are satisfied:
npm startThis is live mode.
Before a real run, verify:
dryRuninuser-config.jsonis what you expect- wallet key is set
- RPC URL works
llmProvideris correct- if using
codex,codex loginhas already been done on this machine - the dashboard loads
- the first screening and management cycles complete without errors
- Telegram is registered if you enabled it
Meridian uses both .env and user-config.json.
Resolution order:
.envis loaded first.user-config.jsonbackfills key env values only when the env var is missing.- Runtime config is built from
user-config.json, then env fallbacks, then code defaults.
In practice:
rpcUrlcan populateRPC_URLwalletKeycan populateWALLET_PRIVATE_KEYllmProvidercan populateLLM_PROVIDERllmModelcan populateLLM_MODELdryRuncan populateDRY_RUN
Per-role model precedence:
managementModel/screeningModel/generalModelLLM_MODEL- provider default
So LLM_MODEL is only a global fallback. The main live settings are the per-role model fields in user-config.json.
.env: secrets and optional overridesuser-config.json: primary runtime settingsuser-config.example.json: reference config shapeautoresearch.json: prompt experiment statelessons.json: performance-derived lessons
Typical .env:
LLM_PROVIDER=claude
RPC_URL=https://...helius-rpc.com
WALLET_PRIVATE_KEY=your_base58_key
HELIUS_API_KEY=your_helius_key
OPENROUTER_API_KEY=sk-or-...
DEEPSEEK_API_KEY=sk-...
MINIMAX_API_KEY=...
LPAGENT_API_KEY=key1,key2
TELEGRAM_BOT_TOKEN=123456:ABC...
TELEGRAM_CHAT_ID=
DRY_RUN=trueNotes:
LLM_PROVIDERcan beclaude,codex,openrouter,deepseek, orminimaxOPENROUTER_API_KEYis only needed when provider isopenrouterDEEPSEEK_API_KEYis only needed when provider isdeepseekMINIMAX_API_KEYis only needed when provider isminimaxclaudeandcodexproviders use OAuth login, no API key neededTELEGRAM_CHAT_IDcan be left empty; Meridian can register it automaticallyDRY_RUN=trueis the safest default until you validate behavior
If you run Meridian in a normal terminal, it starts:
- the web server
- cron jobs
- the PnL watcher
- the REPL
On startup it may preload candidate pools. In that interactive flow:
- entering
1,2,3, and so on deploys into the numbered startup candidate gostarts autonomous mode without an immediate manual deploy
If Meridian is started without an interactive terminal, it still:
- starts the web server
- starts cron jobs
- starts the PnL watcher
It simply skips the REPL prompt.
On launch Meridian typically:
- loads env and config
- initializes Nuggets memory
- deduplicates lessons
- restores any active autoresearch experiment
- starts the web server
- starts Telegram polling if configured
- starts the PnL watcher
- starts management and screening cron cycles
Meridian is intentionally conservative about overlapping work.
- management and screening cycles do not run on top of each other
- management can defer if another action is already in progress
- screening can skip if max positions are reached
- screening can skip if wallet balance is too low
- management can skip when there are no open positions
- the PnL watcher runs independently from the main cycles
If the bot looks idle, check logs for skipped, deferred, or balance / max-position guards before assuming it is broken.
Common commands:
1,2,3... deploy into numbered startup candidategostart autonomous mode without manual deploy/statusshow wallet and open positions/candidatesshow current top candidates/briefingshow performance briefing/thresholdsshow screening thresholds/learnrun pool study/evolveevolve screening thresholds/stopgraceful shutdown<wallet_address>inspect another wallet- free-form text chat with the general agent
The web UI exposes the same chat surface and a command palette.
Telegram supports the same command style once configured.
Important ownership rule:
- the first Telegram chat to message the bot becomes the registered owner
- that chat ID is persisted into
user-config.json - messages from other chats are ignored
Telegram can receive:
- deploy notifications
- close notifications
- out-of-range alerts
- PnL watcher auto-close alerts
- management cycle reports
- screening cycle reports
- daily briefing messages
Default dashboard URL:
http://localhost:3737
The dashboard is websocket-driven and live-updated. On connect it receives an initial payload, then refreshes wallet, positions, timers, candidates, and activity as the bot runs.
Main areas:
- status bar with timers and wallet state
- chat panel
- dashboard tab for wallet, LP overview, and positions
- candidates tab
- activity tab
If the dashboard does not load in normal bot mode, make sure the frontend was built:
cd web
npm install
npm run build
cd ..npm run dev:web is for frontend development only. It is not required for normal bot operation.
Everything in user-config.json is optional, but these are the main knobs.
| Field | Purpose |
|---|---|
rpcUrl |
Solana RPC URL |
walletKey |
Solana wallet private key |
dryRun |
Simulate or trade live |
llmProvider |
claude, codex, openrouter, deepseek, or minimax |
managementModel |
manager model |
screeningModel |
screener model |
generalModel |
chat model |
autoresearchModel |
prompt-optimizer model |
| Field | Meaning |
|---|---|
minFeeActiveTvlRatio |
minimum fee / active TVL |
minTvl, maxTvl |
TVL bounds |
minVolume |
minimum pool volume |
minOrganic |
minimum organic score |
minHolders |
minimum holder count |
minMcap, maxMcap |
market-cap bounds |
minBinStep, maxBinStep |
bin-step bounds |
maxVolatility |
volatility ceiling |
maxPriceChangePct |
price-change ceiling |
timeframe |
screening timeframe |
category |
discovery bucket |
minTokenFeesSol |
anti-bundle / anti-spam floor |
athTopThresholdPct |
ATH proximity threshold |
| Field | Meaning |
|---|---|
deployAmountSol |
baseline SOL per deploy |
maxPositions |
maximum concurrent positions |
minSolToOpen |
minimum wallet balance to allow new deploy |
gasReserve |
reserve left for gas |
positionSizePct |
dynamic sizing fraction |
minClaimAmount |
minimum amount worth claiming |
outOfRangeBinsToClose |
OOR threshold in bins |
outOfRangeWaitMinutes |
OOR hold time before action |
minVolumeToRebalance |
minimum volume to justify rebalance logic |
emergencyPriceDropPct |
emergency-drop cutoff |
stopLossPct |
stop-loss threshold |
takeProfitFeePct |
take-profit threshold |
trailingTakeProfit |
enable trailing exits |
trailingTriggerPct |
trailing activation point |
trailingDropPct |
trailing giveback threshold |
priorityFeeLevel |
transaction fee preset |
pnlUnit |
sol or usd display |
| Field | Meaning |
|---|---|
managementIntervalMin |
management cycle cadence |
screeningIntervalMin |
screening cycle cadence |
healthCheckIntervalMin |
health-check cadence |
pnlWatcherIntervalSec |
watcher cadence |
maxSteps |
max ReAct steps per agent turn |
| Field | Meaning |
|---|---|
temperature |
generation temperature |
maxTokens |
max tokens per turn |
managementFallbackModel |
optional manager fallback |
screeningFallbackModel |
optional screener fallback |
generalFallbackModel |
optional general fallback |
| Field | Meaning |
|---|---|
autoresearch |
enable prompt experiments |
autoresearchModel |
model used for prompt edits |
autoresearchReasoningEffort |
Codex reasoning effort for autoresearch |
autoresearchMinCloses |
closes required per trial |
autoresearchImprovementPct |
keep threshold |
autoresearchDeclinePct |
revert threshold |
autoresearchCooldownCloses |
cooldown between experiments |
| Field | Meaning |
|---|---|
darwinianWeights |
enable adaptive signal weights |
darwinianWindowDays |
lookback window |
darwinianBoostFactor |
positive adjustment multiplier |
darwinianDecayFactor |
negative adjustment multiplier |
darwinianWeightFloor |
lower bound |
darwinianWeightCeiling |
upper bound |
darwinianMinSamples |
minimum sample count |
Every closed position can produce a structured lesson in lessons.json. Lessons are deduplicated and injected into prompts by role.
Prompt budget shape:
- pinned lessons up to 10
- role-matched lessons up to 15
- recent lessons fill the remaining budget up to 35 total
Nuggets provides persistent cross-session memory in data/nuggets/. Meridian uses multiple recall channels during management context building, including pool name, strategy plus bin step, strategy only, volatility bucket, and general lesson recall.
High-hit facts can be promoted into longer-lived memory context. The dashboard also exposes structured nugget stats so the memory system is inspectable, not opaque.
Meridian can evolve screening thresholds from real performance and lesson history. These changes persist back into user-config.json.
Autoresearch is prompt optimization driven by real closes.
It:
- waits until there is enough close history
- identifies the weakest prompt section
- proposes one targeted prompt change
- runs that change over later closes
- keeps, reverts, or discards it based on trial performance
Current section targets:
screener_criteriamanager_logicrange_selection
Important safeguards:
- it requires a minimum data gate before starting
- if the first 3 trial closes are all losses, it reverts early
- keep / revert uses a composite score based on win rate and average PnL
- kept overrides persist across restarts in
autoresearch.json
Autoresearch is experimental. Results can be confounded if other adaptive systems, such as Darwinian weighting, also change behavior during the same evaluation window.
Meridian uses:
- Meteora DLMM SDK for on-chain positions and transactions
- Meteora discovery / PnL endpoints for pool and position data
- Helius RPC for chain access
- Jupiter for token data and swaps
- LP Agent for overview, history, and top-LPer study
Hive Mind is optional collective intelligence.
What it can share:
- lessons
- deploy outcomes
- threshold tendencies
- pool and strategy consensus
What it should not share:
- wallet private keys
- raw wallet balances
- wallet addresses
Registration:
node -e "import('./hive-mind.js').then(m => m.register('https://meridian-hive-api-production.up.railway.app', 'YOUR_TOKEN'))"This stores Hive Mind credentials in user-config.json.
meridian/
index.js
agent.js
prompt.js
config.js
state.js
lessons.js
autoresearch.js
memory.js
server.js
telegram.js
llm-provider.js
tools/
web/
Set either:
WALLET_PRIVATE_KEYin.env- or
walletKeyinuser-config.json
Verify:
codex login
codex exec --model gpt-5.4 "Reply with OK"If the direct CLI call fails, Meridian will fail too.
Build the frontend:
cd web
npm install
npm run build
cd ..Check for:
dryRun- max-position guard
- low SOL balance
- deferred management or screening
- no open positions for management
Only the first registered chat is accepted. Clear telegramChatId in user-config.json if you want to rebind ownership.
This software is provided as-is, without warranty. Running an autonomous trading agent carries real financial risk and can lose funds. Start in dry run, validate behavior, and size capital conservatively.