# breakhearts/jqcli architecture

> Architecture diagram of the GitHub repository breakhearts/jqcli, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/breakhearts/jqcli
- Repository: https://github.com/breakhearts/jqcli

## Overview

1. **What this repo is**
   - `jqcli` is a Python 3.9+ tool for automating JoinQuant workflows: authentication, strategy CRUD, formal backtests/compile runs, backtest inspection, and community post discovery.
   - The repo is organized around one external boundary: the real JoinQuant web UI/API. Most features are wrappers over server-rendered pages and JSON endpoints rather than a public SDK.

2. **Top-level architecture**
   - There are three major surfaces:
     - a **command-line interface** for interactive and automation use,
     - an **HTTP/API client layer** that speaks to JoinQuant,
     - a **web subapp** for local management/archiving tasks.
   - Shared concerns such as config loading, credential precedence, error codes, and output formatting are centralized so both CLI and web flows behave consistently.

3. **CLI entrypoint and command routing**
   - `jqcli/cli.py` is the root entrypoint; `jqcli/commands/*` splits behavior by domain: `auth`, `strategy`, `backtest`, `community`, and `web`.
   - This layer is thin: it parses arguments, enforces interactivity/confirmation rules, and delegates to API/service objects.
   - The CLI is designed for machine consumption first: JSON output, non-interactive mode, and explicit exit codes are part of the contract.

4. **Configuration and credential resolution**
   - `jqcli/config.py` handles environment-file loading, persistent local config, API base URL selection, timeout, and saved credential lookup.
   - Credential precedence matters architecturally: command-line overrides environment variables, which override saved local config, with login able to persist cookies back to config.
   - This is the main boundary between local state and remote access; all downstream API calls depend on a resolved auth context.

5. **Core HTTP/API layer**
   - `jqcli/api/client.py` is the shared transport foundation, with domain modules in `jqcli/api/auth.py`, `strategy.py`, `backtest.py`, and `community.py`.
   - These modules encapsulate JoinQuant-specific endpoints, request/response shaping, and parsing of HTML-rendered pages as well as JSON APIs.
   - The architecture separates “transport + endpoint details” from command logic, so the same API client can be reused by CLI commands, web services, and scripts.

6. **Domain subsystems**
   - **Auth**: login/status/import/logout flows, with support for cookies and tokens.
   - **Strategy**: list/show/new/edit/delete strategies, including source-code handling and ID resolution quirks from JoinQuant pages.
   - **Backtest**: run/list/show/stats/result/logs/delete for both formal backtests and compile-run mode.
   - **Community**: list latest posts, fetch full post details, clone strategy from a post, and enrich with backtest stats.
   - Each subsystem maps closely to a JoinQuant workflow, so the architecture is endpoint-driven rather than object-model-driven.

7. **Output, errors, and machine-readable behavior**
   - `jqcli/output.py` standardizes table vs JSON rendering, and `jqcli/errors.py` normalizes user-facing failures into stable codes.
   - The repo treats error handling as part of the public API: not authenticated, not found, usage error, network/API failure, file failure, confirmation required, and timeout each have distinct exit codes.
   - This makes the CLI suitable for automation pipelines and downstream scripts that need deterministic failure semantics.

8. **Web subapplication**
   - `jqcli/web/app.py`, `routes.py`, `templates/*`, and `static/*` form a server-rendered local UI.
   - `jqcli/web/db.py` suggests a local persistence layer, while the web UI likely serves as an admin/inspection interface rather than a public-facing application.
   - The web app is backed by the same domain concepts as the CLI, but with additional local orchestration around posts, jobs, and archival state.

9. **Web services layer**
   - `jqcli/web/services/*` contains higher-level orchestration:
     - `archive_sync.py` for incremental synchronizing of community data,
     - `posts.py` / `post_labels.py` for post-centric storage and metadata,
     - `backtest_runner.py` for managing backtest execution flows,
     - `strategy_download.py` for retrieving strategy code,
     - `code_standardizer.py` for normalizing source,
     - `jobs.py` for background/job coordination.
   - This layer is the bridge between the remote JoinQuant APIs and local persistent records, and it is where multi-step workflows are composed.

10. **Scripts as operational pipelines**
    - `scripts/archive_community_posts.py` is the clearest batch pipeline in the repo: it syncs community lists, enriches details, and optionally hydrates backtest statistics into a canonical JSONL archive.
    - The other scripts are inspection/probing tools used to reverse-engineer or validate JoinQuant behaviors and payload shapes.
    - These scripts sit outside the CLI contract but reuse the same API and service boundaries, which indicates the project supports both ad hoc automation and repeatable data collection.

11. **Data flow for the main use cases**
    - For strategy/backtest commands: user input → config/credential resolution → API client → JoinQuant page/API → parsed result → formatted output.
    - For community archival: list page crawl → optional detail fetch → optional backtest stats fetch → local JSONL/database state → future incremental sync or UI display.
    - For the web app: browser/UI request → local route handler → web service orchestration → remote JoinQuant API and/or local DB → rendered HTML/JSON.

12. **Testing and repository boundaries**
    - `tests/test_api`, `tests/test_commands`, `tests/test_web.py`, and `tests/test_config.py` show the repo is organized around testing each boundary separately: transport parsing, CLI behavior, config precedence, and web behavior.
    - This mirrors the architecture: API parsing is tested apart from command handling, and the web app is tested apart from the CLI.
    - The presence of a design doc and progress tracking files also suggests the repo is under active evolution, with architecture decisions documented alongside implementation.

13. **External service dependency**
    - The only major external system is JoinQuant itself; all interesting business behavior depends on its real login flow, server-rendered pages, and private JSON endpoints.
    - The repo’s architecture is therefore best understood as a client and orchestration layer around JoinQuant, with local persistence and automation tooling added on top.

Main entry points: [`jqcli/api/client.py`](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/client.py) (HTTP client), [`jqcli/cli.py`](https://github.com/breakhearts/jqcli/blob/master/jqcli/cli.py) (CLI entry), [`jqcli/commands/auth.py`](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/auth.py) (Auth cmd), [`jqcli/config.py`](https://github.com/breakhearts/jqcli/blob/master/jqcli/config.py) (Config)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_cli["CLI surface"]
  node_jqcli_cli["CLI entry<br/>entrypoint<br/>[cli.py]"]
  node_jqcli_cmd_auth["Auth cmd<br/>command<br/>[auth.py]"]
  node_jqcli_cmd_strategy["Strategy cmd<br/>command<br/>[strategy.py]"]
  node_jqcli_cmd_backtest["Backtest cmd<br/>command<br/>[backtest.py]"]
  node_jqcli_cmd_community["Community cmd<br/>command<br/>[community.py]"]
  node_jqcli_cmd_web["Web cmd<br/>command<br/>[web.py]"]
end

subgraph group_core["Core client"]
  node_jqcli_config["Config<br/>settings<br/>[config.py]"]
  node_jqcli_errors["Errors<br/>contract<br/>[errors.py]"]
  node_jqcli_output["Output<br/>presentation<br/>[output.py]"]
  node_jqcli_api_client["HTTP client<br/>transport<br/>[client.py]"]
  node_jqcli_api_auth["Auth API<br/>endpoint wrappers<br/>[auth.py]"]
  node_jqcli_api_strategy["Strategy API<br/>endpoint wrappers<br/>[strategy.py]"]
  node_jqcli_api_backtest["Backtest API<br/>endpoint wrappers<br/>[backtest.py]"]
  node_jqcli_api_community["Community API<br/>endpoint wrappers<br/>[community.py]"]
end

subgraph group_web["Web app"]
  node_jqcli_web_app["Web app<br/>server<br/>[app.py]"]
  node_jqcli_web_routes["Routes<br/>routing<br/>[routes.py]"]
  node_jqcli_web_db[("Local DB<br/>storage<br/>[db.py]")]
  node_jqcli_web_services["Web services<br/>orchestration"]
end

subgraph group_ops["Scripts and tests"]
  node_jqcli_script_archive["Archive script<br/>pipeline"]
  node_jqcli_scripts_probe["Probe scripts<br/>analysis tools<br/>[probe_joinquant.py]"]
  node_jqcli_tests["Boundary tests<br/>test suite"]
end

node_joinquant{{"JoinQuant<br/>external system"}}

node_jqcli_cli -->|"routes"| node_jqcli_cmd_auth
node_jqcli_cli -->|"routes"| node_jqcli_cmd_strategy
node_jqcli_cli -->|"routes"| node_jqcli_cmd_backtest
node_jqcli_cli -->|"routes"| node_jqcli_cmd_community
node_jqcli_cli -->|"routes"| node_jqcli_cmd_web
node_jqcli_cmd_auth -->|"resolve auth"| node_jqcli_config
node_jqcli_cmd_strategy -->|"resolve auth"| node_jqcli_config
node_jqcli_cmd_backtest -->|"resolve auth"| node_jqcli_config
node_jqcli_cmd_community -->|"resolve auth"| node_jqcli_config
node_jqcli_cmd_auth -->|"calls"| node_jqcli_api_auth
node_jqcli_cmd_strategy -->|"calls"| node_jqcli_api_strategy
node_jqcli_cmd_backtest -->|"calls"| node_jqcli_api_backtest
node_jqcli_cmd_community -->|"calls"| node_jqcli_api_community
node_jqcli_cmd_auth -->|"renders"| node_jqcli_output
node_jqcli_cmd_strategy -->|"renders"| node_jqcli_output
node_jqcli_cmd_backtest -->|"renders"| node_jqcli_output
node_jqcli_cmd_community -->|"renders"| node_jqcli_output
node_jqcli_cmd_auth -->|"maps failures"| node_jqcli_errors
node_jqcli_api_client -->|"talks to"| node_joinquant
node_jqcli_api_auth -->|"uses"| node_jqcli_api_client
node_jqcli_api_strategy -->|"uses"| node_jqcli_api_client
node_jqcli_api_backtest -->|"uses"| node_jqcli_api_client
node_jqcli_api_community -->|"uses"| node_jqcli_api_client
node_jqcli_api_auth -->|"auth pages"| node_joinquant
node_jqcli_api_strategy -->|"strategy pages"| node_joinquant
node_jqcli_api_backtest -->|"backtest pages"| node_joinquant
node_jqcli_api_community -->|"community pages"| node_joinquant
node_jqcli_web_app -->|"serves"| node_jqcli_web_routes
node_jqcli_web_routes -->|"delegates"| node_jqcli_web_services
node_jqcli_web_services -->|"persists"| node_jqcli_web_db
node_jqcli_web_services -->|"reuses"| node_jqcli_api_client
node_jqcli_script_archive -->|"crawls"| node_jqcli_api_community
node_jqcli_script_archive -->|"writes archive"| node_jqcli_web_db
node_jqcli_scripts_probe -->|"probes"| node_jqcli_api_client
node_jqcli_tests -->|"covers"| node_jqcli_config
node_jqcli_tests -->|"covers"| node_jqcli_api_client
node_jqcli_tests -->|"covers"| node_jqcli_web_app

click node_jqcli_cli "https://github.com/breakhearts/jqcli/blob/master/jqcli/cli.py"
click node_jqcli_cmd_auth "https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/auth.py"
click node_jqcli_cmd_strategy "https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/strategy.py"
click node_jqcli_cmd_backtest "https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/backtest.py"
click node_jqcli_cmd_community "https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/community.py"
click node_jqcli_cmd_web "https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/web.py"
click node_jqcli_config "https://github.com/breakhearts/jqcli/blob/master/jqcli/config.py"
click node_jqcli_errors "https://github.com/breakhearts/jqcli/blob/master/jqcli/errors.py"
click node_jqcli_output "https://github.com/breakhearts/jqcli/blob/master/jqcli/output.py"
click node_jqcli_api_client "https://github.com/breakhearts/jqcli/blob/master/jqcli/api/client.py"
click node_jqcli_api_auth "https://github.com/breakhearts/jqcli/blob/master/jqcli/api/auth.py"
click node_jqcli_api_strategy "https://github.com/breakhearts/jqcli/blob/master/jqcli/api/strategy.py"
click node_jqcli_api_backtest "https://github.com/breakhearts/jqcli/blob/master/jqcli/api/backtest.py"
click node_jqcli_api_community "https://github.com/breakhearts/jqcli/blob/master/jqcli/api/community.py"
click node_jqcli_web_app "https://github.com/breakhearts/jqcli/blob/master/jqcli/web/app.py"
click node_jqcli_web_routes "https://github.com/breakhearts/jqcli/blob/master/jqcli/web/routes.py"
click node_jqcli_web_db "https://github.com/breakhearts/jqcli/blob/master/jqcli/web/db.py"
click node_jqcli_script_archive "https://github.com/breakhearts/jqcli/blob/master/scripts/archive_community_posts.py"
click node_jqcli_scripts_probe "https://github.com/breakhearts/jqcli/blob/master/scripts/probe_joinquant.py"
click node_jqcli_tests "https://github.com/breakhearts/jqcli/tree/master/tests"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_jqcli_cli,node_jqcli_cmd_auth,node_jqcli_cmd_strategy,node_jqcli_cmd_backtest,node_jqcli_cmd_community,node_jqcli_cmd_web toneBlue
class node_jqcli_config,node_jqcli_errors,node_jqcli_output,node_jqcli_api_client,node_jqcli_api_auth,node_jqcli_api_strategy,node_jqcli_api_backtest,node_jqcli_api_community toneAmber
class node_jqcli_web_app,node_jqcli_web_routes,node_jqcli_web_db,node_jqcli_web_services toneMint
class node_jqcli_script_archive,node_jqcli_scripts_probe,node_jqcli_tests toneRose
class node_joinquant toneNeutral
```

## Components

### CLI surface

Command-line entrypoint, routing, and user-facing automation contract.

- [CLI entry](https://github.com/breakhearts/jqcli/blob/master/jqcli/cli.py): entrypoint · Root command entrypoint and argument dispatch. · `jqcli/cli.py`
- [Auth cmd](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/auth.py): command · Login, status, import, and logout flows. · `jqcli/commands/auth.py`
- [Strategy cmd](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/strategy.py): command · Strategy CRUD and code handling commands. · `jqcli/commands/strategy.py`
- [Backtest cmd](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/backtest.py): command · Backtest and compile-run command flows. · `jqcli/commands/backtest.py`
- [Community cmd](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/community.py): command · Community post discovery and strategy cloning commands. · `jqcli/commands/community.py`
- [Web cmd](https://github.com/breakhearts/jqcli/blob/master/jqcli/commands/web.py): command · Starts or manages the local web application. · `jqcli/commands/web.py`

### Core client

Shared config, transport, endpoint wrappers, and result handling.

- [Config](https://github.com/breakhearts/jqcli/blob/master/jqcli/config.py): settings · Environment, persistent config, URL, timeout, and credential precedence. · `jqcli/config.py`
- [Errors](https://github.com/breakhearts/jqcli/blob/master/jqcli/errors.py): contract · Stable exit codes and normalized failures. · `jqcli/errors.py`
- [Output](https://github.com/breakhearts/jqcli/blob/master/jqcli/output.py): presentation · JSON and table rendering for CLI output. · `jqcli/output.py`
- [HTTP client](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/client.py): transport · Shared request/session transport for JoinQuant access. · `jqcli/api/client.py`
- [Auth API](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/auth.py): endpoint wrappers · JoinQuant login and session management endpoints. · `jqcli/api/auth.py`
- [Strategy API](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/strategy.py): endpoint wrappers · Strategy listing, editing, creation, and deletion endpoints. · `jqcli/api/strategy.py`
- [Backtest API](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/backtest.py): endpoint wrappers · Formal backtest and compile-run endpoints plus result parsing. · `jqcli/api/backtest.py`
- [Community API](https://github.com/breakhearts/jqcli/blob/master/jqcli/api/community.py): endpoint wrappers · Community posts, post details, and enrichment endpoints. · `jqcli/api/community.py`

### Web app

Local server-rendered UI and orchestration services.

- [Web app](https://github.com/breakhearts/jqcli/blob/master/jqcli/web/app.py): server · Local Flask-style application entrypoint. · `jqcli/web/app.py`
- [Routes](https://github.com/breakhearts/jqcli/blob/master/jqcli/web/routes.py): routing · HTTP route handlers for the local UI. · `jqcli/web/routes.py`
- [Local DB](https://github.com/breakhearts/jqcli/blob/master/jqcli/web/db.py): storage · Local persistence boundary for posts and jobs. · `jqcli/web/db.py`
- **Web services**: orchestration · Higher-level workflows bridging JoinQuant and local state.

### Scripts and tests

Operational pipelines, probes, and boundary-focused tests.

- [Archive script](https://github.com/breakhearts/jqcli/blob/master/scripts/archive_community_posts.py): pipeline · Batch sync pipeline for community archive generation. · `scripts/archive_community_posts.py`
- [Probe scripts](https://github.com/breakhearts/jqcli/blob/master/scripts/probe_joinquant.py): analysis tools · Inspection scripts used to reverse-engineer and validate JoinQuant behavior. · `scripts/probe_joinquant.py`
- [Boundary tests](https://github.com/breakhearts/jqcli/tree/master/tests): test suite · Tests for config, API parsing, command behavior, and web behavior. · `tests`

### Other components

- **JoinQuant**: external system · Remote web UI and private JSON endpoints that the repo automates.

## Connections

- CLI entry → Auth cmd: routes · CLI dispatches auth subcommands.
- CLI entry → Strategy cmd: routes · CLI dispatches strategy subcommands.
- CLI entry → Backtest cmd: routes · CLI dispatches backtest subcommands.
- CLI entry → Community cmd: routes · CLI dispatches community subcommands.
- CLI entry → Web cmd: routes · CLI dispatches web subcommands.
- Auth cmd → Config: resolve auth · Commands load config and credential context.
- Strategy cmd → Config: resolve auth · Strategy commands depend on resolved config.
- Backtest cmd → Config: resolve auth · Backtest commands depend on resolved config.
- Community cmd → Config: resolve auth · Community commands depend on resolved config.
- Auth cmd → Auth API: calls · Auth commands delegate to auth API wrapper.
- Strategy cmd → Strategy API: calls · Strategy commands delegate to strategy API wrapper.
- Backtest cmd → Backtest API: calls · Backtest commands delegate to backtest API wrapper.
- Community cmd → Community API: calls · Community commands delegate to community API wrapper.
- Auth cmd → Output: renders · CLI formats auth results for JSON/table output.
- Strategy cmd → Output: renders · CLI formats strategy results for JSON/table output.
- Backtest cmd → Output: renders · CLI formats backtest results for JSON/table output.
- Community cmd → Output: renders · CLI formats community results for JSON/table output.
- Auth cmd → Errors: maps failures · Commands normalize user-facing failures to exit codes.
- HTTP client → JoinQuant: talks to · Shared transport targets JoinQuant.
- Auth API → HTTP client: uses · Auth endpoints use shared HTTP client.
- Strategy API → HTTP client: uses · Strategy endpoints use shared HTTP client.
- Backtest API → HTTP client: uses · Backtest endpoints use shared HTTP client.
- Community API → HTTP client: uses · Community endpoints use shared HTTP client.
- Auth API → JoinQuant: auth pages · Auth flows call remote login/session pages.
- Strategy API → JoinQuant: strategy pages · Strategy flows interact with remote pages and JSON.
- Backtest API → JoinQuant: backtest pages · Backtest flows interact with remote pages and JSON.
- Community API → JoinQuant: community pages · Community flows interact with remote pages and JSON.
- Web app → Routes: serves · Web app mounts route handlers.
- Routes → Web services: delegates · Routes delegate business logic to services.
- Web services → Local DB: persists · Services read and write local persistent state.
- Web services → HTTP client: reuses · Web workflows reuse shared transport to reach JoinQuant.
- Archive script → Community API: crawls · Archive pipeline fetches community list and details.
- Archive script → Local DB: writes archive · Archive pipeline can hydrate local canonical state.
- Probe scripts → HTTP client: probes · Inspection scripts exercise transport and parsing behavior.
- Boundary tests → Config: covers · Tests verify config precedence and resolution.
- Boundary tests → HTTP client: covers · Tests verify transport and parsing boundaries.
- Boundary tests → Web app: covers · Tests verify web behavior separately from CLI.
