Skip to content

Work in a monorepo

Config discovery walks up from the directory you run gth in, so you don’t have to sit in the repo root or pass a path. From any package subdirectory, gth finds the nearest .gsloth.config.* above you — up to, and including, your repo root.

The main use case: one shared config at the repo root

Section titled “The main use case: one shared config at the repo root”

Goal: keep a single .gsloth.config.json at the monorepo root and have every package use it, whatever subdirectory you invoke gth from.

acme-platform/
├── .git/
├── .gsloth.config.json
└── packages/
└── api/
└── src/server.ts

Run gth from inside the package:

Terminal window
cd packages/api
gth ask "summarise src/server.ts"

Discovery walks up packages/apipackagesacme-platform, finds .gsloth.config.json at the root, and uses it. The walk searches each directory from the current one upward and stops at (and including) the first directory that contains .git, your home directory, or the filesystem root — whichever comes first. So a config at or below the git root is found; one above it is not. In a monorepo the .git sits at the root, which is exactly where the shared config lives, so the walk lands there and no per-package setup is needed.

Two details that decide which file wins:

  • Nearest directory wins — discovery returns the first match and stops; it does not merge configs from several directories. Within one directory the format order is .gsloth.config.json.jsonc.js.mjs.
  • The root config may live either at acme-platform/.gsloth.config.json or, for a tidier root, at acme-platform/.gsloth/.gsloth-settings/.gsloth.config.json; both are discovered by the same walk.

If a package is itself a git submodule (its own .git), the walk stops at that submodule’s root and never reaches the monorepo root — put a config there, or pass one with -c.

Drop a .gsloth.config.json into the package directory. Because the nearest match wins, runs inside that package use it:

acme-platform/
├── .gsloth.config.json # used everywhere else
└── packages/
└── ml/
└── .gsloth.config.json # used for runs inside packages/ml

The package config replaces the root config for those runs — it is not merged with it — so it must be complete on its own (at minimum a valid llm spec). The only layer that merges underneath a discovered project config is the global ~/.gsloth config, so genuinely cross-cutting settings belong there rather than being duplicated into each package.

Discovery answers the question above for a command you run inside a package. A review is not that shape: gth review and gth pr run once, from the repo root, over a diff that can span several packages at once. One run, one config, one guidelines file — and no single directory for the walk to start from, so nothing on this page so far can give the API package’s rules to the API half of a diff.

The usual workaround is to write the per-package rules into the review instructions as prose — “for files under packages/api, apply…” — and leave the model to apply the right ones. It works, and it is a judgement call on every run: nothing outside the answer shows which rules were used, and it decays quietly as packages are added.

prompts.paths makes that selection deterministic instead, before the model is called. Each entry names the paths it covers and the file to attach for them:

{
"prompts": {
"guidelines": "AGENTS.md",
"paths": [
{ "name": "api", "match": ["packages/api/**"], "guidelines": ".gsloth/guidelines/api.md" },
{ "name": "ml", "match": ["packages/ml/**"], "guidelines": ".gsloth/guidelines/ml.md" }
]
}
}
Terminal window
gth review --content-source git

A diff confined to packages/api is reviewed against AGENTS.md plus the API guidelines, with the ML ones left out, and the run reports which entries it attached. The glob vocabulary, the other six segments, and what each outcome reports: Path-scoped prompts.

Terminal window
# From any package subdir — finds the repo-root .gsloth.config.json by walking up
cd packages/api && gth ask "summarise src/server.ts"
# Skip discovery entirely and point gth at a specific config file
gth -c ./.gsloth.config.json ask "who are you?"
# Package-local config: runs inside packages/ml use packages/ml/.gsloth.config.json
cd packages/ml && gth ask "which model is configured here?"