A monorepo containing multiple Haskell applications and libraries, built with Bazel and featuring a NodeJS-based task management tool.
This repository is organized as a Bazel-based monorepo with the following structure:
- Haskell Applications (haskell/app/): Standalone executable applications
- Haskell Libraries (haskell/libs/): Shared libraries and reusable components
- Electron Applications (electron-app/): Cross-platform desktop applications with Haskell backends
- Task Manager (tools/mcp-shrimp-task-manager/): TypeScript/NodeJS-based task management tool
- Build System: Bazel with Stackage integration for Haskell dependency management
- Build System: Bazel
- Haskell: Managed via Stackage snapshots
- TypeScript/NodeJS: PNPM for dependency management
- Code Formatting: Fourmolu/Ormolu (Haskell), Prettier (TypeScript)
├── haskell/
│   ├── app/           # Haskell applications (executables)
│   └── libs/          # Haskell libraries (shared code)
├── electron-app/      # Electron desktop applications
│   └── aivika-population-viz/  # Population growth visualization
├── tools/
│   └── mcp-shrimp-task-manager/  # TypeScript task manager
├── MODULE.bazel       # Bazel module configuration
├── WORKSPACE          # Bazel workspace configuration
└── stackage_snapshot.json  # Haskell dependency snapshot
- Bazel
- Haskell toolchain (managed by Bazel)
- Node.js and PNPM (for task manager)
- Clone the repository
- Install task manager dependencies:
bazel run -- @pnpm//:pnpm --dir $PWD/tools/mcp-shrimp-task-manager/ install
# Build all targets
bazel build //...
# Run all tests
bazel test //...
# Build a specific application
bazel build //haskell/app/<app-name>:<app-name>
# Run a specific application
bazel run //haskell/app/<app-name>:<app-name>Haskell dependencies are managed through Stackage snapshots. To add a new dependency:
- 
Add the package to MODULE.bazel:stack.package(name = "package-name") 
- 
Update the Stackage snapshot: bazel run @stackage-unpinned//:pin -- --upgrade-hackage 
- 
Use the dependency in your BUILD.bazel:deps = ["@stackage//:package-name"] 
For the task manager, dependencies are managed with PNPM:
cd tools/mcp-shrimp-task-manager
pnpm add <package-name>- Use Fourmolu or Ormolu for formatting
- Follow Haddock documentation standards
- PascalCase for modules, types, and type classes
- camelCase for functions and variables
- Use Prettier for formatting
- Follow standard TypeScript naming conventions
- Group imports: external packages → project modules → relative imports
- Use Buildifier to format BUILD files
- Each application and library must have its own BUILD.bazelfile
- Create directory: haskell/app/<app-name>/
- Add BUILD.bazelwithhaskell_binaryrule
- Add source files (e.g., Main.hs)
- Create directory: haskell/libs/<lib-name>/
- Add BUILD.bazelwithhaskell_libraryrule
- Organize source files by module structure
- Use the scalpellibrary for all web scraping
- Respect robots.txtand set descriptive User-Agent headers
- Write unit tests with local HTML fixtures
To install the dependencies for the task manager, run the following command from the root of the workspace:
bazel run -- @pnpm//:pnpm --dir $PWD/tools/mcp-shrimp-task-manager/ installThis project includes an interactive Electron application for visualizing population growth simulations powered by the Aivika system dynamics library.
- Real-time WebSocket Communication: Haskell backend with Electron frontend
- Interactive Visualization: Chart.js-powered population growth charts
- Customizable Parameters: Adjustable initial population, growth rate, and simulation time
- Multiple Views: Chart view, raw data table, and mathematical analysis
- Data Export: CSV and JSON export functionality
- Mathematical Model: Implements exponential growth (dP/dt = r × P)
To run the complete Aivika population growth visualization (both Haskell server and Electron frontend):
# Run the complete demo with both server and client
bazel run //electron-app/aivika-population-viz:aivika-demo
# Run in development mode with developer tools
bazel run //electron-app/aivika-population-viz:aivika-demo-devYou can also run the components individually:
# Run just the Haskell backend in CLI mode
bazel run //haskell/app/aivika-population-growth:aivika-population-growth
# Run the Haskell backend in WebSocket server mode
bazel run //haskell/app/aivika-population-growth:aivika-population-growth -- --server --port 9161
# Run just the Electron visualization app (requires running server separately)
bazel run //electron-app/aivika-population-viz:aivika-population-vizWhen running the Haskell backend in CLI mode, you can customize parameters:
INITIAL_POP=500 GROWTH_RATE=0.03 TIME_END=10 bazel run //haskell/app/aivika-population-growth:aivika-population-growthTo update and pin Haskell dependencies:
bazel run @stackage-unpinned//:pin- Create a feature branch from main
- Make changes following the code standards
- Update corresponding BUILD.bazelfiles
- Run bazel build //...andbazel test //...
- Format code with appropriate formatters
- Commit and open a pull request
- DO NOT modify files in bazel-*directories
- DO NOT use Cabal or Stack directly for Haskell package management
- DO NOT use npm or yarn in the task manager (use PNPM)
- DO NOT commit directly to the mainbranch
- DO NOT modify stackage_snapshot.jsonmanually