Stahl Capital: GUI application built with portfolio_rs
  • TypeScript 77.6%
  • Rust 11.4%
  • Nix 8.1%
  • CSS 2%
  • Shell 0.6%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
dependabot[bot] f6a9e118c2
chore(deps-dev): bump oxlint from 1.76.0 to 1.77.0 in /frontend (#19)
* chore(deps-dev): bump oxlint from 1.76.0 to 1.77.0 in /frontend

Bumps [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) from 1.76.0 to 1.77.0.
- [Release notes](https://github.com/oxc-project/oxc/releases)
- [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md)
- [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.77.0/npm/oxlint)

---
updated-dependencies:
- dependency-name: oxlint
  dependency-version: 1.77.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(nix): update frontendDepsHash

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-10 19:59:01 +02:00
.github ci: rebase before pushing frontendDepsHash commits 2026-08-01 19:28:24 +02:00
frontend chore(deps-dev): bump oxlint from 1.76.0 to 1.77.0 in /frontend (#19) 2026-08-10 19:59:01 +02:00
screenshots docs: replace img/ with new screenshots, add hero shot to README 2026-07-06 14:40:27 +02:00
scripts ci: run frontendDepsHash fixup via pull_request_target 2026-08-01 13:16:44 +02:00
src-tauri fix: exit cleanly when no display server is set 2026-08-01 12:41:45 +02:00
.envrc initial commit 2026-07-06 13:03:59 +02:00
.gitignore initial commit 2026-07-06 13:03:59 +02:00
AGENTS.md ci: dependabot deps plus auto frontendDepsHash and flake.lock PRs 2026-08-01 13:12:50 +02:00
Cargo.lock chore(deps): bump tokio from 1.52.3 to 1.53.1 2026-08-01 13:04:51 +02:00
Cargo.toml initial commit 2026-07-06 13:03:59 +02:00
flake.lock chore(nix): update flake.lock (#21) 2026-08-10 19:58:30 +02:00
flake.nix chore(deps-dev): bump oxlint from 1.76.0 to 1.77.0 in /frontend (#19) 2026-08-10 19:59:01 +02:00
LICENSE initial commit 2026-07-06 13:03:59 +02:00
README.md docs: add Run and Install sections 2026-08-01 12:41:45 +02:00

Stahl Capital

CI

A local-first desktop GUI for portfolio_rs — track investment portfolios, run policy-aware reviews, simulate rebalancing, and manage a durable finance workspace, all from a native app. Built with Tauri 2, React, and TypeScript.

Performance view

Status: early prototype. Expect rough edges.

Features

  • Dashboard — total value, day change, and PnL at a glance
  • Positions — add, edit, and remove holdings with live quotes
  • Allocation — asset-class breakdown with drift visualization
  • Performance — historical and daily returns, top movers
  • Context — agent-friendly portfolio briefing
  • Validate — sanity-check a portfolio file
  • Workspace mode — for full finance workspaces (portfolio_rs init-workspace):
    • Policy — view and edit your machine-readable investment policy
    • Review — policy-aware drift/violation checks
    • Simulate — rebalancing what-if scenarios (never trades)
    • Documents — generate weekly reports and decision records
  • Settings — currency, theme, and AI provider configuration

Run

nix run github:MarkusZoppelt/stahl

Install

nix profile install github:MarkusZoppelt/stahl

Native installers (.dmg, .deb/.AppImage, .msi) are attached to GitHub Releases.

Building

nix build .#stahl      # ./result/bin/stahl
nix run .#stahl        # build + run
nix develop            # cargo, pnpm, cargo-tauri, rust-analyzer, …
cargo tauri dev

If cargo tauri dev fails with a dyld/libiconv error, you likely have a stale cargo-tauri binary in ~/.cargo/bin (installed via cargo install tauri-cli) that shadows the one provided by the dev shell. Either remove it, or invoke cargo-tauri dev directly (skipping cargo's subcommand resolution, which always prefers $CARGO_HOME/bin).

Without Nix

Requires Rust (stable), Node.js, pnpm, and the platform prerequisites for Tauri 2 (WebKitGTK + GTK3 on Linux; Xcode command line tools on macOS).

pnpm --dir frontend install
cargo install tauri-cli --version "^2"
cd src-tauri
cargo tauri dev     # development
cargo tauri build   # release bundle

Development

Frontend linting and formatting use Oxlint and Oxfmt — fast, Rust-based drop-ins for ESLint and Prettier:

pnpm --dir frontend lint        # oxlint
pnpm --dir frontend fmt         # oxfmt (writes)
pnpm --dir frontend fmt:check   # oxfmt --check

nix flake check runs the full suite in one shot: the release build, cargo clippy --deny warnings, cargo fmt --check, and the frontend lint/format/typecheck. nix fmt formats the Nix code itself (via Alejandra). CI (.github/workflows/ci.yml) runs nix flake check on Linux and macOS for every push and pull request.

Releases

Pushing a tag matching v* (e.g. v0.1.0) triggers .github/workflows/release.yml, which builds native installers with tauri-action — macOS (Apple Silicon) .dmg/.app, Linux .deb/.AppImage, and Windows .msi/.exe — and attaches them to a draft GitHub Release. This is a separate, non-Nix pipeline: nix build produces binaries dynamically linked against /nix/store paths (fine for machines with Nix, not for end-user distribution), so releases are built with each OS's native toolchain instead, the same way as the "Without Nix" section above. macOS builds are ad-hoc signed (signingIdentity: "-" in tauri.conf.json) since there's no Apple Developer certificate configured; users will still need to right-click → Open (or clear the quarantine attribute) on first launch.

Project structure

src-tauri/    Rust backend (Tauri commands, AppState wiring, config)
frontend/     React + TypeScript + Tailwind UI
flake.nix     Reproducible build for macOS, Linux, and NixOS

The Rust side is a thin layer: src-tauri/src/commands.rs exposes portfolio_rs::state::AppState methods as Tauri commands; almost all domain logic (portfolio math, policy review, simulation, reports) lives in the portfolio_rs library.

License

MIT — see LICENSE.