This repo is for all subprojects. # Goals of this project The Omni project is to leverage automation and asymmetries to create wealth. The target of the wealth is Bitcoin. The means: write everything down, first in English, then in code. Resources defined in the repo can be used to quickly create and release products. New technology shall be prototyped and developed as needed. Since Bitcoin always goes up, as long as we are acquiring more Bitcoin, then we are growing our wealth. There is a limit to the amount of wealth that one person needs, roughly defined as how much is required to live a modest life and provide for one's family. Once this is achieved, excess wealth shall be deployed to improve the world through activist entrepreneurship. # Developer Guide Here we define the tools and infrastructure for all dev work. ## Goals of the workflow - have minimal ceremony - default to asynchrony, but allow for synchronous work when necessary - automate the boring stuff - standardize environments, tooling, and versions to minimize friction while collaborating - support the longevity and self-sustainability of the project Ideally, each contributor should be able to go off grid for a day or a week or more, continue working offline, submit their work when finished, and have no or minimal conflicts. This also refers to the resilience of the production systems. We should never need "out of office" email auto-replies, or urgent contact. No pager duty, no daily stand-ups. Yes, this policy will affect what code we write, not just how we write it; that is by design. ## Source Layout The source tree maps to the module namespace, and roughly follows the Haskell namespace hierarchy. This is true of all languages: Python, Scheme, Rust, C, etc. Namespaces are formatted either as file paths, like `Omni/Dev`, or dot-separated, like `Omni.Dev`. Parts of the namespace should always be capitalized. The namespace for all products that we own is `Biz`, this includes proprietary applications, products, and related infrastructure. The `Omni` namespace is used for internal development tooling and infrastructure that are shared between all other projects. Stuff that can be open sourced or otherwise externalized should be outside of `Biz` or `Omni`. Related code should be kept close together. This means that you should start with small namespaces: use `Omni/Thing.hs` before `Omni/Thing/Service.hs`. Try to keep all related code in one spot for as long as possible. Re-use code from the `Omni/` namespace as much as possible. For example, use `Omni/Cli.hs` or `Omni/Test.py` instead of trying to roll your own code for cli parsing or running test suites. If the the namespace doesn't have the feature you need, then add the feature. Boundaries and interfaces between namespaces should be singular and well-defined. Likewise, the functionality and purpose of a particular namespace should be singular and well-defined. Follow the unix principle of "do one thing and do it well." Namespaces are always capitalized. In Scheme and Python this actually translates quite well and helps distinguish between types/classes/modules and values. ## Available tools We provide some tools for working with projects in the omnirepo: ### bild `bild` is our universal build tool. It can build and test everything in the repo. #### Examples `bild --test Omni/Bild.hs` will build and test the `Omni/Bild.hs` namespace. Use this command to run tests for a namespace. `bild --time 0 Omni/Cloud.nix` will build the `Omni/Cloud.nix` namespace, which is our cloud VM instance. The `--time 0` argument disables the timeout (which defaults to 10 minutes), this is useful for longer builds. `bild --plan Omni/Test.hs` this just does the analysis step, and prints a description of the build as JSON. It will not build anything. ### lint The `lint` command is a universal lint and formatting tool. It will error if any lints fail, or if the code is not formatted properly. Use `lint --fix` to autofix any lints or autoformat where possible. #### Examples `lint Omni/Cli.hs` will lint the `Omni/Cli.hs` namespace and report any errors. `lint --fix **/*.py` will lint and fix all Python files in the repo. ### repl.sh This is like `nix-shell` but specific to our repo. It will analyze the given namespace, pull in all necessary dependencies, and start a bash shell or language-specific repl. #### Examples `repl.sh Omni/Bild.hs` this creates a nix shell for the `Omni/Bild.hs` namespace, and starts a Haskell repl using `ghci` with the namespace already loaded. `repl.sh --bash Omni/Log.py` this creates a nix shell for `Omni/Log.py`, but starts a bash shell for the namespace instead of a Python repl. ## Coding Conventions There are some conventions we use for every program, across every language in use. 1. At the command line interface, the program must take `test` as a first argument, which will run the program's test suite. This is used as a standard interface for running tests in CI. 2. The entrypoint for every program shall be called `main.` In Python, the convention `if __name__ == "__main__"` is not necessary because `bild` wraps the program in a call like `python -m main`; the same is true of Guile scheme. ## Setting up remote builds The `Omni.Dev` machine acts as a remote build server and Nix cache. To use it from your local machine, your public key must be at `Omni/Keys/$USER.pub` and your user added to `Omni/Users.nix`, then bild will automatically use your key to run builds on `Omni.Dev`. To use distributed builds for all nix commands, add the following to your NixOS configuration: nix = { distributedBuilds = true; buildMachines = [ { hostName = "dev.simatime.com"; sshUser = "yourUserName"; sshKey = "/path/to/your/private/key"; system = "x86_64-linux"; supportedFeatures = [ "x86_64-linux" "big-parallel" ]; } ]; };