{"id":50816440,"url":"https://github.com/simontarara62/capitalcom-cli","last_synced_at":"2026-06-13T10:02:55.740Z","repository":{"id":364474697,"uuid":"1267738438","full_name":"SimonTarara62/capitalcom-cli","owner":"SimonTarara62","description":"Safety-first command-line client for the Capital.com Open API — market data, accounts, guarded trading, watchlists, and real-time streaming.","archived":false,"fork":false,"pushed_at":"2026-06-13T07:16:41.000Z","size":81,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T07:21:16.422Z","etag":null,"topics":["api-client","capital-com","cfd","cli","finance","fintech","market-data","python","rich","trading","trading-api","typer"],"latest_commit_sha":null,"homepage":"https://github.com/SimonTarara62/capitalcom-cli","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimonTarara62.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T20:21:32.000Z","updated_at":"2026-06-13T07:16:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SimonTarara62/capitalcom-cli","commit_stats":null,"previous_names":["simontarara62/capitalcom-cli"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/SimonTarara62/capitalcom-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonTarara62%2Fcapitalcom-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonTarara62%2Fcapitalcom-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonTarara62%2Fcapitalcom-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonTarara62%2Fcapitalcom-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimonTarara62","download_url":"https://codeload.github.com/SimonTarara62/capitalcom-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonTarara62%2Fcapitalcom-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34279898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","capital-com","cfd","cli","finance","fintech","market-data","python","rich","trading","trading-api","typer"],"created_at":"2026-06-13T10:02:55.020Z","updated_at":"2026-06-13T10:02:55.724Z","avatar_url":"https://github.com/SimonTarara62.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# capctl — Capital.com CLI\n\nA fast, scriptable command-line client for the [Capital.com](https://capital.com) Open API, built with Typer and Rich.\n\nBrowse markets, manage accounts and watchlists, preview and execute trades behind multiple safety guardrails, and stream real-time prices — from your terminal, in human-readable tables or raw JSON for automation.\n\n[![CI](https://github.com/SimonTarara62/capitalcom-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/SimonTarara62/capitalcom-cli/actions/workflows/ci.yml)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)\n[![Release](https://img.shields.io/github/v/release/SimonTarara62/capitalcom-cli?sort=semver)](https://github.com/SimonTarara62/capitalcom-cli/releases)\n\n```text\n$ capctl market search \"gold\"\nMarkets\n┏━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┓\n┃ epic   ┃ instrumentName ┃ bid     ┃ offer   ┃ marketStatus ┃\n┡━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━┩\n│ GOLD   │ Gold           │ 2331.05 │ 2331.35 │ TRADEABLE    │\n└────────┴────────────────┴─────────┴─────────┴──────────────┘\n```\n\n\u003e **New to this?** The [getting-started guide](docs/getting-started.md) walks you from zero (no account, no API key) to your first practice trade on a demo account. Hit a problem? See [troubleshooting](docs/troubleshooting.md).\n\n\u003e **Risk disclaimer:** This is an unofficial tool, not affiliated with or endorsed by Capital.com, and nothing here is financial advice. CFD trading carries a high risk of losing money. The CLI defaults to the **demo** environment and disables trading until you explicitly opt in — keep it that way until you know exactly what you're doing. Use at your own risk.\n\n## Why capctl?\n\nThe Capital.com web platform is built for clicking; `capctl` is built for **repeating, scripting, and automating**. Anything you do through it can be put in a shell script, a cron job, or a pipeline — with machine-readable JSON output and exit codes you can branch on. And unlike ad-hoc API scripts, every action goes through the same safety layer: demo by default, trading off by default, an explicit market allowlist, size and daily-order limits, and a two-phase preview→execute flow that makes \"oops, wrong size\" structurally hard.\n\n**Who gets value from it:**\n\n- **Traders who live in the terminal** — check positions, P\u0026L, and orders in seconds without opening a browser; set a price alert and keep working.\n- **People learning to trade** — practice the full lifecycle (research → preview → execute → manage → close) on a demo account with virtual money, with guardrails on from the start. The [getting-started guide](docs/getting-started.md) assumes zero experience.\n- **Developers building on the Capital.com API** — `--json` output mirrors the real API responses, so `capctl` doubles as an interactive API explorer while you build your own integration; the risk-engine pattern (allowlist, limits, preview/confirm) is reusable as a reference.\n- **Data and automation folks** — pull historical OHLC candles into CSV/pandas, log portfolio snapshots from cron, monitor markets from scripts, wire alerts into anything that can run a shell command.\n\nSee [practical use cases](docs/use-cases.md) for worked, copy-pasteable scenarios.\n\n## Features\n\n- **Six command groups** covering the full Open API surface: `session`, `market`, `account`, `trade`, `watchlist`, `stream`\n- **Safety-first trading** — trading is off by default; enabling it requires an explicit EPIC allowlist, every execution goes through a two-phase *preview → execute* flow with risk checks, and mutating commands require `--yes`\n- **`--json` everywhere** — every command can emit raw JSON for piping into `jq`, scripts, or CI jobs\n- **Distinct exit codes per failure class** — scripts can branch on *why* a command failed (auth vs. risk-block vs. upstream error)\n- **Real-time streaming** — live price tables, price-level alerts, and portfolio snapshots over WebSocket\n- **Demo and live environments** — defaults to demo; live requires explicit opt-in\n- **Built-in rate limiting** — client-side token buckets respect Capital.com's 10 req/s global, 1 req/s session, and trading-burst limits\n\n## Installation\n\nRequires Python 3.10+.\n\n**One-line install (recommended)** — isolated, global `capctl` command, no clone:\n\n```bash\npipx install git+https://github.com/SimonTarara62/capitalcom-cli.git\n```\n\nUsing [uv](https://docs.astral.sh/uv/) instead of pipx:\n\n```bash\nuv tool install git+https://github.com/SimonTarara62/capitalcom-cli.git\n```\n\nPlain pip (into the active environment):\n\n```bash\npip install git+https://github.com/SimonTarara62/capitalcom-cli.git\n```\n\n**From a clone (for development):**\n\n```bash\ngit clone https://github.com/SimonTarara62/capitalcom-cli.git\ncd capitalcom-cli\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e .\n```\n\nVerify and enable shell completion (bash/zsh/fish, provided by Typer):\n\n```bash\ncapctl --version\ncapctl --install-completion\n```\n\n## Configuration\n\nGenerate an API key in the Capital.com platform under **Settings → API integrations**, then:\n\n```bash\ncp .env.example .env\n# edit .env and fill in CAP_API_KEY, CAP_IDENTIFIER, CAP_API_PASSWORD\n```\n\nCredentials are resolved in this order:\n\n1. `--env-file PATH` flag\n2. `$CAP_ENV_FILE` environment variable\n3. `./.env` in the current directory\n4. `~/.config/capital-cli/.env`\n\nAll settings (one `CAP_*` variable each) and their defaults:\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `CAP_ENV` | `demo` | `demo` or `live` |\n| `CAP_API_KEY` | — | API key (required) |\n| `CAP_IDENTIFIER` | — | Login email (required) |\n| `CAP_API_PASSWORD` | — | API-key custom password (required) |\n| `CAP_ALLOW_TRADING` | `false` | Master switch for all trade execution |\n| `CAP_ALLOWED_EPICS` | (empty) | Comma-separated allowlist, or `ALL` |\n| `CAP_MAX_POSITION_SIZE` | `1.0` | Per-trade size ceiling |\n| `CAP_MAX_WORKING_ORDER_SIZE` | `1.0` | Per-order size ceiling |\n| `CAP_MAX_OPEN_POSITIONS` | `3` | Open-position cap |\n| `CAP_MAX_ORDERS_PER_DAY` | `20` | Daily order counter |\n| `CAP_REQUIRE_EXPLICIT_CONFIRM` | `true` | Mutations need `--yes` |\n| `CAP_DRY_RUN` | `false` | Block all executions regardless of other flags |\n| `CAP_DEFAULT_ACCOUNT_ID` | (none) | Account selected after login |\n| `CAP_HTTP_TIMEOUT_S` | `15` | HTTP timeout |\n| `CAP_LOG_LEVEL` | `WARNING` | `DEBUG` … `CRITICAL` |\n| `CAP_WS_ENABLED` | `false` | Required for `capctl stream …` |\n\nTrade previews and the daily order counter persist between commands in\n`~/.config/capital-cli/state.json` (override with `CAPCTL_STATE_FILE`).\n\n## Global flags\n\nThese go **before** the command group:\n\n| Flag | Purpose |\n|------|---------|\n| `--json` | Emit raw JSON instead of tables |\n| `--demo` / `--live` | Force environment for this invocation |\n| `--env-file PATH` | Use a specific credentials file |\n| `--account ID`, `-a` | Use a specific account |\n| `--verbose`, `-v` | Debug logging (incl. per-command timing) |\n| `--version` | Print version and exit |\n\n## Command reference\n\n### Session\n\n```bash\ncapctl session status            # local session state (no network call)\ncapctl session details           # server-side session info (client/account ids, timezone)\ncapctl session time              # broker server time (no auth)\ncapctl session encryption-key    # API encryption key for encrypted-password login\ncapctl session login [--force] [--account ID]\ncapctl session ping              # keep the session alive\ncapctl session switch ACCOUNT_ID\ncapctl session logout\n```\n\nNote: commands that need authentication log in automatically; an explicit `login` is rarely required.\n\n### Market data\n\n```bash\ncapctl market search \"bitcoin\" [--limit 20]\ncapctl market search --epics GOLD,SILVER\ncapctl market get GOLD                          # details + dealing rules\ncapctl market nav-root                          # top-level categories\ncapctl market nav-node NODE_ID                  # drill into a category\ncapctl market prices GOLD --resolution HOUR --max 48\ncapctl market sentiment GOLD                    # client long/short %\ncapctl market sentiment GOLD,SILVER,BTCUSD      # batch sentiment for several markets\ncapctl market nav-node NODE_ID --limit 50       # cap the number of children returned\n```\n\nPrice resolutions: `MINUTE`, `MINUTE_5`, `MINUTE_15`, `MINUTE_30`, `HOUR`, `HOUR_4`, `DAY`, `WEEK`.\n\n### Account\n\n```bash\ncapctl account list\ncapctl account prefs-get\ncapctl account prefs-set --hedging --yes        # risk-gated\ncapctl account prefs-set --leverage CRYPTOCURRENCIES=2 --leverage CURRENCIES=20 --yes\ncapctl account history-activity --last 3600\ncapctl account history-transactions --last 86400 [--type DEPOSIT]\ncapctl account topup 1000 --yes                 # demo environment only\n```\n\n### Trading\n\nRead-only:\n\n```bash\ncapctl trade positions\ncapctl trade position DEAL_ID\ncapctl trade orders\ncapctl trade confirm DEAL_REFERENCE [--wait --timeout 30]\n```\n\nTwo-phase execution — preview first (validates against the risk policy and broker dealing rules, **creates nothing**), then execute with the returned `preview_id`:\n\n```bash\ncapctl trade preview-position GOLD BUY 0.5 --stop-distance 10 --profit-distance 20\n# → returns preview_id, risk-check table, estimated entry\n\ncapctl trade execute-position \u003cpreview_id\u003e --yes\n```\n\nWorking orders follow the same shape:\n\n```bash\ncapctl trade preview-order GOLD BUY LIMIT 2300 0.5 --good-till 2026-07-01T00:00:00\ncapctl trade execute-order \u003cpreview_id\u003e --yes\n```\n\nClosing and cancelling:\n\n```bash\ncapctl trade close DEAL_ID --yes\ncapctl trade cancel DEAL_ID --yes\n```\n\nAmending an open position or a pending order (stops, limits, level, expiry):\n\n```bash\ncapctl trade amend-position DEAL_ID --stop-level 2300 --profit-level 2450 --yes\ncapctl trade amend-order DEAL_ID --level 2310 --good-till 2026-08-01T00:00:00 --yes\n```\n\nPreviews expire after 120 seconds. Execution commands wait for broker confirmation by default (`--no-wait` to skip; `--timeout` to tune).\n\n### Watchlists\n\n```bash\ncapctl watchlist list\ncapctl watchlist get WATCHLIST_ID\ncapctl watchlist create \"Metals\" --yes\ncapctl watchlist add WATCHLIST_ID GOLD --yes\ncapctl watchlist remove WATCHLIST_ID GOLD --yes\ncapctl watchlist delete WATCHLIST_ID --yes\n```\n\n### Streaming (requires `CAP_WS_ENABLED=true`)\n\n```bash\ncapctl stream prices GOLD,SILVER,EURUSD --duration 120     # live updating table\ncapctl stream candles GOLD,BTCUSD --resolution MINUTE_5         # live OHLC candlesticks\ncapctl stream candles BTCUSD --resolution HOUR --type heikin-ashi\ncapctl stream alerts GOLD 2400 --direction ABOVE           # beep when crossed\ncapctl stream portfolio --duration 300 --interval 5        # snapshots for open positions\n```\n\nStreams stop after `--duration` seconds or Ctrl-C. Capital.com allows at most 40 concurrent EPIC subscriptions.\n\n## Use cases\n\nQuick recipes below; for fuller worked scenarios (paper-trading practice, data analysis, cron monitoring, safe automation, API exploration) see [docs/use-cases.md](docs/use-cases.md).\n\n**Morning check — one screen of context:**\n\n```bash\ncapctl account list \u0026\u0026 capctl trade positions \u0026\u0026 capctl trade orders\n```\n\n**Scripting with `--json` and `jq` — extract the GOLD bid:**\n\n```bash\ncapctl --json market search --epics GOLD | jq -r '.markets[0].bid'\n```\n\n**Export 200 daily candles to a CSV:**\n\n```bash\ncapctl --json market prices GOLD --resolution DAY --max 200 \\\n  | jq -r '.prices[] | [.snapshotTime, .openPrice.bid, .highPrice.bid, .lowPrice.bid, .closePrice.bid] | @csv' \\\n  \u003e gold_daily.csv\n```\n\n**Safe trade in the demo environment, end to end:**\n\n```bash\n# .env: CAP_ENV=demo, CAP_ALLOW_TRADING=true, CAP_ALLOWED_EPICS=GOLD\nPREVIEW=$(capctl --json trade preview-position GOLD BUY 0.5 --stop-distance 15 | jq -r .preview_id)\ncapctl trade execute-position \"$PREVIEW\" --yes\ncapctl trade positions\n```\n\n**Branch on failure class in a script:**\n\n```bash\ncapctl --json trade execute-position \"$PREVIEW\" --yes\ncase $? in\n  0) echo \"filled\" ;;\n  4) echo \"blocked by safety policy (trading disabled / confirm / risk limit)\" ;;\n  5) echo \"auth problem — check credentials\" ;;\n  7) echo \"broker/upstream error — retry later\" ;;\nesac\n```\n\n**Watch for a breakout while you work:**\n\n```bash\ncapctl stream alerts BTCUSD 75000 --direction ABOVE --duration 3600\n```\n\n**Cron-driven snapshot (JSON logs, no tables):**\n\n```bash\n*/15 * * * * capctl --json trade positions \u003e\u003e ~/logs/positions.jsonl 2\u003e\u00261\n```\n\n## Exit codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Success |\n| 1 | Unexpected internal error |\n| 2 | Invalid input (bad parameter or failed validation) |\n| 3 | Configuration error (missing/invalid credentials) |\n| 4 | Safety policy block (trading disabled, dry-run, confirm required, EPIC not allowed, risk limit) |\n| 5 | Authentication/session failure |\n| 6 | Local rate limit exceeded |\n| 7 | Broker / upstream API error |\n| 8 | Preview not found, expired, or failed checks |\n| 130 | Interrupted (Ctrl-C) |\n\n## Safety model\n\nTrade execution must pass **all** of these gates, in order:\n\n1. `CAP_ALLOW_TRADING=true` — master switch (default off)\n2. `CAP_DRY_RUN=false` — dry-run blocks everything\n3. `--yes` on the command (when `CAP_REQUIRE_EXPLICIT_CONFIRM=true`)\n4. A valid, unexpired preview whose risk checks all passed:\n   - EPIC is in `CAP_ALLOWED_EPICS`\n   - size within `CAP_MAX_POSITION_SIZE`, normalized to the broker's min/max/increment dealing rules\n   - daily order counter under `CAP_MAX_ORDERS_PER_DAY`\n\nThere is no way to skip the preview step for positions and working orders — `execute-*` commands only accept a `preview_id`.\n\n**Live trading:** keep `CAP_ENV=demo` until your workflow is proven. Switching to live requires editing `.env` (or passing `--live`) *and* having trading enabled — the defaults protect you twice.\n\n## Architecture\n\n```\ncapital_cli/\n├── core/        # Capital.com services: config, HTTP client, session,\n│                # rate limiter, risk engine, models, errors, WebSocket\n└── cli/         # presentation: Typer apps per command group,\n                 # Rich/JSON output, async runner with exit-code mapping\n```\n\nThe `cli/` layer never talks to the API directly — every command parses arguments, calls a `core` service, and renders the result. All risk validation lives in `core/risk.py`, so safety rules cannot be bypassed by output or argument handling.\n\n## Development\n\n```bash\npip install -e \".[dev]\"\npytest -q              # full test suite\nruff check .           # lint\nmypy capital_cli/cli   # type-check the CLI layer\n```\n\nAn opt-in end-to-end suite runs against the real demo API (credentials required):\n\n```bash\nCAPCTL_E2E=1 pytest tests/e2e -m e2e -v\n```\n\nTests mock the HTTP and WebSocket layers — no network or credentials needed.\n\n## Documentation\n\n- [Getting started from zero](docs/getting-started.md) — account, API key, install, first trade\n- [Practical use cases](docs/use-cases.md) — what people actually do with capctl, with copy-pasteable scenarios\n- [Troubleshooting](docs/troubleshooting.md) — common errors and exit codes\n- [Contributing](CONTRIBUTING.md) — dev setup and conventions\n\n## License\n\nApache License 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).\n\nLicensed under the Apache License, Version 2.0. You may obtain a copy at\n\u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e. Unless required by applicable law\nor agreed to in writing, software distributed under the License is distributed\non an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimontarara62%2Fcapitalcom-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimontarara62%2Fcapitalcom-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimontarara62%2Fcapitalcom-cli/lists"}