CLI Commands
The Grit CLI is a single binary that scaffolds projects, generates full-stack resources, and syncs types between Go and TypeScript. Running grit new is interactive by default -- it walks you through architecture mode and frontend selection. Install it once and use it across all your Grit projects.
The CLI across a project's life
Four commands carry a Grit project from empty folder to production. Everything else — migrate, seed, sync, studio — slots in between these stages.
Installing the CLI
Install the Grit CLI globally using Go:
$ grit generate resource Invoice -iDefining fields for InvoiceEnter fields as name:type (e.g., title:string)Valid types: string, text, int, uint, float, bool, datetime, date, slug, belongs_to, many_to_manyPress Enter with no input when done.> number:string✓ Added number (string)> amount:float✓ Added amount (float)> status:string✓ Added status (string)> due_date:date✓ Added due_date (date)> paid:bool✓ Added paid (bool)>
More Examples
grit plugin
Install and remove plugins. A plugin generates code into your project — models, routes, pages — which you then own and can edit. Everything an install does is recorded in .grit/plugins.lock.json, and removal replays that record backwards, so uninstalling is exact rather than best-effort. Commit the lockfile.
See Plugins for writing your own, and Multi-tenancy for the first-party one.
grit remove resource
Remove a previously generated resource. This deletes the Go model, service, handler, Zod schemas, TypeScript types, React hooks, resource definition, and admin page. It also cleans up all injection markers that were added when the resource was generated.
Syntax
grit remove resource <Name># Shorthand aliasgrit rm resource <Name>
The resource name should be the singular PascalCase name (e.g., Post, Product, BlogCategory) — the same name you used with grit generate resource.
grit add role
Add a new role to your project. This command updates all relevant files across the stack in one step — Go model constants, TypeScript types, Zod schemas, shared constants, and admin panel resource definitions (badge, filter, and form options).
This single command updates 7 locations across your project:
- Go model constants (RoleModerator = "MODERATOR")
- Zod schema enum validation
- TypeScript union type
- ROLES constants object
- Admin badge configuration
- Admin table filter options
- Admin form select options
The role name is automatically uppercased. Multi-word roles use underscores:grit add role CONTENT_MANAGER
grit start
Start development servers for your Grit project. Use subcommands to launch the frontend client apps or the Go API server individually.
grit start client
Runs pnpm dev from the project root, which starts all frontend apps (web, admin, expo, docs) via Turborepo.
grit start server
Runs go run cmd/server/main.go from the apps/api directory to start the Go API server.
Both commands auto-detect the project root by looking for docker-compose.yml or turbo.json, so you can run them from any subdirectory within your project.
grit test
Runs every test suite in the project — Go, the frontend suites, and with --e2e the Playwright tests — then prints one report. Which suites exist depends on the architecture you scaffolded, and this command works that out for you.
Flags
| --go | Run only the Go tests |
| --node | Run only the frontend tests |
| --e2e | Include the Playwright suite (needs the app running) |
| --race | Enable the Go race detector |
| --cover | Report Go coverage |
A suite that cannot run is reported as SKIP with the reason, never dropped from the report. A runner that silently runs nothing looks exactly like one that passed, and that is the most expensive kind of green.
End-to-end tests are opt-in because they need the API and frontends already running — failing against a server that was never started tells you nothing about your code. The command exits non-zero if any suite fails, so it drops straight into CI.
grit sync
Parse all Go model files and regenerate the corresponding TypeScript types and Zod schemas in the shared package. Use this command whenever you manually modify a Go model and want the frontend types to stay in sync.
How It Works
- Finds the project root by walking up directories looking for docker-compose.yml or turbo.json
- Scans all .go files in apps/api/internal/models/
- Parses each file using Go's AST (Abstract Syntax Tree) parser to extract struct definitions
- For each struct, reads field names, Go types, JSON tags, and GORM tags
- Maps Go types to TypeScript types and Zod validators
- Writes TypeScript interface files to packages/shared/types/
- Writes Zod schema files to packages/shared/schemas/
- Skips the User model (which has custom hand-written schemas)
When to Use It
- ✓After manually adding or removing fields from a Go model
- ✓After changing a field's type in a Go struct
- ✓After modifying GORM tags (e.g., adding type:text)
- ✓After adding a completely new model file manually (without using grit generate)
Note: You do not need to run grit sync after using grit generate resource. The generator already creates the TypeScript types and Zod schemas for the new resource.
grit upgrade
Bring a project's framework files up to the CLI's version: admin components, the web app shell, Docker and root config, the migrate and seed tools. Your resource definitions, handlers, models and .env are not touched.
Since v3.147.0 it also does not touch framework files you have edited. Grit records what it wrote and its hash in .grit/manifest.json, so an upgrade can tell a file nobody has opened from one you have customised. Untouched files are replaced. Edited ones are listed and left exactly as they are.
grit upgrade✓ Upgrade complete. Updated 87 files.⚠ Left alone, because you have edited these files since Grit wrote them:apps/admin/components/data-table.tsxapps/admin/components/app-sidebar.tsxgrit upgrade --diff # see what the new version would changegrit upgrade --force # take the new version and lose your edits
--diff prints a unified diff of your version against the new one, so you can port the parts you want by hand. --force overwrites everything, which is what upgrade did unconditionally before this release.
A project created before v3.147.0 has no manifest, so nothing can be said about what has been edited in it, and the first upgrade behaves exactly as it always did. That upgrade writes the manifest, and every one after it is protected. Commit .grit/manifest.json so the protection applies to everyone on the team.
grit update
Update the Grit CLI itself to the latest version. It first checks GitHub for the newest release and exits immediately if you are already up to date. Otherwise it picks a strategy: if the Go toolchain is on your PATH it runs go install ...@<latest>; if Go is not installed it downloads the matching prebuilt binary from the GitHub release and atomically swaps it in. On Windows the running .exe is locked, so the old binary is renamed to .old before the new one is written (and restored if the update fails).
Aliased as grit self-update. Pass --from-release to skip the go install path and always pull the prebuilt binary from the GitHub release.
Note: grit update updates the CLI tool itself. To update your project's scaffold files (admin panel, configs, web app), use grit upgrade instead.
grit version
Print the current version of the Grit CLI.
Operational Commands
Grit ships a set of operational commands inspired by Laravel/Goravel for day-to-day workflows: route inspection, maintenance mode, and one-command deployment.
grit routes
List all registered API routes in a formatted table. Parses your routes.go file and shows the HTTP method, path, handler function, and middleware group.
$ grit routesMETHOD PATH HANDLER GROUP────── ──── ─────── ─────GET /api/health func1 publicPOST /api/auth/register authHandler.Register publicPOST /api/auth/login authHandler.Login publicPOST /api/auth/refresh authHandler.Refresh publicGET /api/auth/me authHandler.Me protectedPOST /api/auth/logout authHandler.Logout protectedPOST /api/auth/totp/setup totpHandler.Setup protectedGET /api/auth/totp/status totpHandler.Status protectedGET /api/users/:id userHandler.GetByID protectedPOST /api/uploads uploadHandler.Create protectedPOST /api/ai/chat aiHandler.Chat protectedDELETE /api/admin/users/:id userHandler.Delete admin16 routes total
Works for both monorepo (apps/api/internal/routes/) and single app (internal/routes/) projects.
grit down / grit up
Toggle maintenance mode. When enabled, all API requests receive a 503 Service Unavailable response.
$ grit downApplication is now in maintenance mode.All requests will receive 503.Run 'grit up' to bring it back online.
$ grit upApplication is back online!Normal request handling has resumed.
How it works
- 1.
grit downcreates a.maintenancefile in the project root - 2.The scaffolded
Maintenance()middleware checks for this file on every request - 3.
grit upremoves the file, resuming normal operation
func Maintenance() gin.HandlerFunc {return func(c *gin.Context) {if _, err := os.Stat(".maintenance"); err == nil {c.JSON(http.StatusServiceUnavailable, gin.H{"error": gin.H{"code": "MAINTENANCE","message": "Application is in maintenance mode.",},})c.Abort()return}c.Next()}}
grit deploy
One-command production deployment. See the dedicated Deploy Command guide for full details.
# Deploy with flagsgrit deploy --host user@server.com --domain myapp.com# Or set env vars in .envDEPLOY_HOST=user@server.comDEPLOY_DOMAIN=myapp.comDEPLOY_KEY_FILE=~/.ssh/id_rsagrit deploy
Quick Reference
| Command | Description |
|---|---|
| grit init | Write CLAUDE.md / AGENTS.md convention docs to the project root |
| grit new <name> | Scaffold a new project (interactive by default) |
| grit new-desktop <name> | Scaffold a standalone Wails desktop app |
| grit new . | Scaffold into the current directory |
| grit new . --force | Scaffold into a non-empty directory |
| grit new myapp --here | Explicit in-place scaffolding |
| grit new <name> --api | Scaffold Go API only |
| grit new <name> --full | Scaffold everything including docs |
| grit new <name> --single | Single architecture (API only) |
| grit new <name> --double | Double architecture (API + web) |
| grit new <name> --triple | Triple architecture (API + web + admin) |
| grit new <name> --vite | Use TanStack Router (Vite) frontend |
| grit new <name> --next | Use Next.js frontend |
| grit new <name> --desktop | Add Wails desktop client (combinable with --triple/--double/--mobile/--api) |
| grit new <name> --mobile --desktop | Multi-client: API + Expo mobile + Wails desktop (shared types) |
| --arch, --frontend | Long-form flags for architecture and frontend |
| grit generate resource <Name> | Generate full-stack CRUD resource |
| grit g resource <Name> | Shorthand for generate resource |
| grit generate seeder <Resource> | Generate a database seeder for existing resources |
| grit generate sequence <Name> | Generate a sequential numbering helper (e.g. INV-202605-0001) |
| grit generate field <Resource> <spec> | Add a column to an existing resource (model + Zod + TS + admin) |
| grit generate perf | Generate a k6 load test (perf/load.js) for the API |
| grit remove resource <Name> | Remove a generated resource and clean up markers |
| grit add role <ROLE> | Add a new role across all project files |
| grit add web-auth | Add page protection helpers to apps/web/ |
| grit expose form <Resource> | Scaffold a public form page for a resource |
| grit expose table <Resource> | Scaffold a paginated list page for a resource |
| grit start | Start every app in the project in parallel |
| grit start client | Start frontend apps via pnpm dev |
| grit start server | Start Go API server (hot-reload via air) |
| grit compile | Build the desktop app executable (Wails) |
| grit package | Build a distributable desktop installer (.exe / .app / binary) |
| grit studio | Open the GORM Studio database browser |
| grit test | Run every test suite and print one report |
| grit mcp serve | Expose the project to AI agents over MCP |
| grit sync | Sync Go models to TypeScript + Zod |
| grit migrate | Run GORM AutoMigrate for all models |
| grit migrate --fresh | Drop all tables then re-migrate |
| grit seed | Populate database with initial data |
| grit backup | Back up the entire database to a ZIP archive |
| grit restore <backup.zip> | Restore the database from a backup archive |
| grit upgrade | Update project scaffold files to latest |
| grit update | Remove old CLI and install latest version |
| grit routes | List all registered API routes |
| grit down | Enable maintenance mode (503) |
| grit up | Disable maintenance mode |
| grit deploy | Deploy to production server |
| grit version | Print CLI version |
Found a bug? Open an issue at https://github.com/MUKE-coder/grit/issues — we fix bugs fast and appreciate every report.
