- TypeScript 77.6%
- Rust 11.4%
- Nix 8.1%
- CSS 2%
- Shell 0.6%
- Other 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
* 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> |
||
| .github | ||
| frontend | ||
| screenshots | ||
| scripts | ||
| src-tauri | ||
| .envrc | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| README.md | ||
Stahl Capital
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.
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
With Nix (recommended)
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 devfails with adyld/libiconverror, you likely have a stalecargo-tauribinary in~/.cargo/bin(installed viacargo install tauri-cli) that shadows the one provided by the dev shell. Either remove it, or invokecargo-tauri devdirectly (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.
