Skip to main content
Currently, when Macroscope reviews a pull request, it’s hyper focused on identifying runtime correctness issues. Our goal remains to maintain the best signal to noise ratio possible, but this means that an entire category of best-practice feedback is left to human reviewers. That’s why we’re introducing an independent review that’s specifically focused on your team’s best practices.
Note: Code review rules is currently in beta. If you would like to use this feature, please contact us at support@macroscope.com.

Setting Up macroscope.md Files

To set up your custom rules, add a macroscope.md file to the root directory of any folder(s) you’d like to set custom rules for.
For repository-wide rules, create a file at the root of your repository.For folder-level rules, create a file in the root of the folder you’d like the rules to apply to.
In the macroscope.md file, list out the best practices relevant to that part of your codebase. Think of these as the idioms and conventions that capture how you want code to be written — from common patterns surfaced during reviews by more experienced developers, to reminders about helpful utilities that are often overlooked. To help you get started, we’ve shared some examples from our own use below. During code review, Macroscope will:
  1. Run a separate CheckRun on the Pull Request, that’s focused on the rules defined in your macroscope.md file(s).
  2. Leave inline comments pointing to the exact code that violates a rule.
  3. Reference the specific rule from your guidelines in each comment.
Your macroscope.md files can always be updated as you see fit.
You can create different macroscope.md files in different folders if folders of your repository follow different conventions.For example, if you have separate backend and frontend folders, you can create separate backend/macroscope.md and frontend/macroscope.md files to set different rules for each folder.Learn about folder-level rule configuration.

Example Rules

Below are a few common use cases:

Style

e.g. To improve clarity and maintain consistent scoping, errors should be if-scoped only when all declared variables are used exclusively within that scope.

Logging Guidelines

e.g. All logs must be structured in JSON format.

Typos

e.g. Literal and formatted strings that might be displayed to the user should be free of typos.

Security

e.g.File Systems should always be accessed using a rooted filesystem operation.

Example macroscope.md File

### Security
- NEVER use personally identifiable customer data (such as passwords, customer IP, names, email addresses, etc.) in debug logs. (Obfuscated identifiers and other publicly available information is fine.)
- File Systems should always be accessed using a rooted filesystem operation.

### Mathutil
Prefer using one of the following `github.com/prassoai/back/utils/mathutil` methods if it can be used without changing the semantics of the code.
`func Map[A any, B any](items []A, m func(in A) B) []B`
`func MapErr[A any, B any](items []A, m func(in A) (B, error)) ([]B, error)`

### Style
- Prefer inlining over introducing temporary variables unless: their value needs to be mutated; is expensive to calculate; is used multiple times; is used in an otherwise unnamed parameter position (for example, a map key); or to meaningfully improve readability because their declaration is several lines long and inlining becomes weird. But, don't prefer assignment expressions in Python.
- When accessing gRPC types, prefer to use Getters instead of direct field access, unless the caller is trying to access the pointer value of an optional field with a scalar type.
- Errors should be if-scoped when all declared variables are used exclusively within that scope.
- Avoid mixing variable assignment and error handling inside a single if-else block.

### Typos
Literal and formatted strings that might be displayed to the user should be free of typos.

Folder-Level Rule Configuration

If you want to create specific rules for specific subfolders within a repository, you can create files named macroscope.md in each of those folders. Multiple macroscope.md files are useful when:
  • You have different languages and frameworks within the same repository.
  • You want distinct rulesets for distinct parts of your project (e.g. backend/ vs. frontend/ subfolders).
  • You have team-specific guidelines that don’t apply globally.
When Macroscope checks which rules apply to a file, it walks up the directory tree and collects macroscope.md files it finds along the way. If you want to stop inheritance at a certain point (e.g. in a multi-language monorepo), name that file macroscope_root.md. If Macroscope encounters a file named macroscope_root.md, it stops climbing, meaning that no rules from parent folders above that point will be applied. Otherwise, Macroscope will merge the macroscope.md rules it finds as it moves up the folder structure.
macroscope_root.md files are optional. If you don’t include any, rules will be inherited from parent folders.

Example Repository Structure with Multiple macroscope.md Rule Files

repo/
├── macroscope.md                        # General, repo-wide rules

├── backend/
│   ├── macroscope.md                    # Go backend–specific rules
│   ├── service/
│   │   ├── macroscope.md                # Narrower rules for service package
│   │   └── handler.go
│   └── utils/
│       └── errors.go

├── frontend/
│   ├── macroscope.md                    # Frontend (TypeScript)–specific rules
│   ├── components/
│   │   ├── macroscope.md                # Component-level rules
│   │   ├── Button.tsx
│   │   └── Modal.tsx
│   └── pages/
│       └── Home.tsx

├── scripts/
    ├── macroscope_root.md               # Stops inheritance from higher folders
    └── deploy.sh