Contributing to StockWise
Thanks for your interest! Contributions of all sizes are welcome — bug reports, docs, new commands, broker integrations, and strategy ideas.
Ground rules
- Be kind. See the Code of Conduct.
- StockWise is a financial tool. Read the Disclaimer — never hard-code real broker credentials, API keys, or personal portfolio data into the repo, tests, or fixtures.
Where to start
Issues labelled good first issue are small and self-contained: each says what to change, links the code, and lists what “done” looks like. Comment on one to claim it so two people don’t work on the same thing. Larger ideas are on the roadmap; open a discussion or issue before starting one.
Getting set up
git clone https://github.com/iamsaquib8/stockwise
cd stockwise
cargo build
cargo test
Requires Rust 1.97+ (edition 2024). We support the latest stable release and the two before it. Optional at runtime: a local Ollama server for AI features and Redis for caching — both degrade gracefully when absent.
Try your build without touching your real portfolio by pointing StockWise at a scratch data directory:
export STOCKWISE_HOME=$(mktemp -d)
cargo run -- doctor
cargo run -- quote RELIANCE TCS
cargo run -- portfolio add TCS 10 3500 && cargo run -- portfolio
Finding your way around
docs/architecture.md maps the source tree. In short:
src/main.rs defines the CLI, src/commands/ holds one file per command area
(overview, technicals, markets, holdings, trade, …), and the
analysis engines (technical.rs, tax.rs, rebalance.rs, verdict.rs,
backtest.rs, intraday.rs, longterm.rs) are pure functions with unit tests.
The tools that stockwise mcp and stockwise ask give to AI assistants are in
src/tools/, the MCP server is src/mcp.rs and the ask loop is src/ask.rs.
Other folders: docs/ (the documentation pages), site/ and site/build.py
(the docs site), changelog.d/ and scripts/changelog.py (the changelog),
packaging/ (installers and package recipes), skills/ (the Agent Skill).
Before you open a PR
Run the same checks CI does — all of them must pass:
cargo fmt --all # format
cargo clippy --all-targets -- -D warnings # lint (must be clean)
cargo clippy --all-targets --no-default-features -- -D warnings # minimal build (no tui/serve/mcp)
cargo clippy --all-targets --features wasm-plugins -- -D warnings # WASM strategy plugins
cargo test # all tests green
cargo test --features wasm-plugins
python3 scripts/changelog.py check # changelog fragments are valid
If you change anything under docs/, site/ or the top-level Markdown pages,
also run python3 site/build.py (it needs mdBook)
and fix every warning and broken link it reports.
- Keep PRs focused: one issue per PR, ideally under about 400 changed lines, with
Closes #Nin the description. Split larger work into a series. - Review your own diff before asking for review, and never merge with failing CI.
- Add tests for new behavior — CLI parsing tests live in
src/main.rs, pure logic tests next to the code. - Update
docs/andREADME.md, and add a changelog fragment (see “Changelog entries”), when behavior changes. - New commands: add the variant to
Commandsand to theGROUPShelp table insrc/main.rs(a test checks every command is grouped), writecmd_<name>in the matchingsrc/commands/*.rsfile, and document it indocs/commands.md. Everystockwise ...command you write in backticks indocs/cheatsheet.mdandskills/stockwise/SKILL.mdmust parse: a test checks them. - New AI tools: a tool is read-only and calls the function behind a command’s
--jsonoutput. Add it tosrc/tools/, list it inpackaging/mcpb/manifest.json(a test compares the two lists) and in the tool table indocs/ai.md. The tool count (stockwise mcp --list-tools) is written inREADME.md,docs/commands.md,docs/ai.md,docs/architecture.mdandpackaging/pypi/README.md: update it. - Errors: return
anyhowerrors (bail!) instead of printing and returningOk(()), so scripts see a non-zero exit code. Empty states (nothing in the portfolio yet) are not errors. - Anything that can place a live order or GTT must go through
place_live_orderinsrc/commands/trade.rs— never callBroker::place_orderorBroker::gtt_createdirectly.
Good first contributions
--json/--csvoutput for another command (analyze,peers,news,picks, …) — build rows once and render them withsrc/output.rs; seecmd_portfolio_showorcmd_riskfor the pattern, and add the shape todocs/commands.md.- More symbols in the India/US universes in
src/market.rs, or a refresh when a ticker changes. - Unit tests for an indicator in
src/technical.rsagainst a known reference. - Docs: a worked example for a command you use.
Adding a data source or broker
Network access goes through src/api.rs (rate limiting, retry, caching). Broker
integrations implement the Broker trait in src/brokers/ — see zerodha.rs
for a compact example. Keep secrets in secrets::Secret fields (stored in the OS
keyring via src/brokers/secrets.rs), never in source, logs or error messages.
Test against brokers::mock::MockServer with fixtures from the broker’s docs, and
label anything not yet run against a live account “experimental”. Give each read
endpoint a Shape (the fields the parser reads and the documented ones) and check
your fixtures with mock::assert_fixture_shapes, so trade selftest can tell
testers when a live response differs. Anything that only reads from a real account
(trade selftest, trade sync) must run on a brokers::readonly::ReadOnly session.
Changelog entries
Do not edit CHANGELOG.md in a pull request: add one small file to
changelog.d/ per user-visible change, so pull requests never conflict. Name it
<issue-or-slug>.<type>.md with a type of added, changed, deprecated,
removed, fixed, performance or security, and put one bullet in it:
- `tax in` counts gold ETFs as non-equity, so they are no longer taxed as listed
shares ([#87](https://github.com/iamsaquib8/stockwise/issues/87)).
- One to three lines, in plain language, saying what the user can now do or what was wrong. Start with the command name in backticks.
- Link the issue.
- No marketing words (“powerful”, “2.0”, “institutional-grade”), no formulas and
no nested lists. Details belong in
docs/. - Credit outside contributors:
Thanks [@name](https://github.com/name).
python3 scripts/changelog.py check validates the files (CI runs it). Maintainers
cut a release with python3 scripts/changelog.py release X.Y.Z; see
changelog.d/README.md.
Commit messages
Use a type and an optional scope, then a short imperative summary under about 72
characters: fix(tax): treat gold ETFs as non-equity. Types: feat, fix,
docs, test, refactor, perf, build, ci, chore. Explain the why in the
body when it isn’t obvious.
How this project is built
StockWise is maintained by one person with help from AI coding assistants
(commits made with one carry a Co-Authored-By line). The same rules apply to
every change, however it was written: a human reads the diff, CI must pass, new
behavior needs tests, and numbers that affect money (tax, XIRR, imports) are
checked against a hand calculation or a fixture. If you use an assistant for a
contribution, that’s fine — you are responsible for understanding and testing
what you submit.
Reporting bugs / requesting features
Use the issue templates. For open-ended ideas, start a Discussion.