# How to Use the /cmd Directory for Main Applications in Go Projects

> Learn to use the cmd directory for main Go applications with the golang-standards/project-layout. Structure executables for clean code and efficient development.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: how-to-guide
- Published: 2026-03-06

---

**The `/cmd` directory holds executable entry-points where each subdirectory corresponds to a binary name, containing only thin `main` wrappers that delegate to reusable packages in `/internal` and `/pkg`.**

The `golang-standards/project-layout` repository defines community-accepted conventions for organizing Go codebases. When you use the `/cmd` directory for main applications, you create a clean separation between executable entry-points and reusable business logic, enabling better testability and code sharing across your organization.

## Purpose of the /cmd Directory

According to the `golang-standards/project-layout` source code, the `/cmd` directory serves as the container for all executable entry-points (binaries) in your project. Each immediate subdirectory inside `/cmd` must be named after the binary you intend to produce—for example, `cmd/myapp` yields a `myapp` executable.

This structure originates from the repository's [cmd/README.md](https://github.com/golang-standards/project-layout/blob/master/cmd/README.md) and the main [README.md `/cmd` section](https://github.com/golang-standards/project-layout/blob/master/README.md#cmd), which document that the directory should contain minimal code.

## Structuring Binary Subdirectories

### Naming Conventions

Name each subdirectory after the resulting binary. For a server named `api` and a CLI tool named `cli`, create:

```

cmd/
  api/
    main.go
  cli/
    main.go

```

### The Thin Wrapper Pattern

The [`main.go`](https://github.com/golang-standards/project-layout/blob/main/main.go) file inside each binary directory should act as a thin wrapper. According to the project layout standards, it contains only the `main` function responsible for wiring together dependencies and invoking core logic defined elsewhere.

## Separating Concerns with /internal and /pkg

To maximize reusability while enforcing boundaries, the `/cmd` directory imports from two critical locations:

**`/internal`** – Private application code that cannot be imported by external projects. The Go compiler enforces this boundary automatically. Place your business logic here, such as [`internal/app/service.go`](https://github.com/golang-standards/project-layout/blob/main/internal/app/service.go).

**`/pkg`** – Public library code intended for consumption by other repositories. External projects may import these packages, as seen in [`pkg/util/helpers.go`](https://github.com/golang-standards/project-layout/blob/main/pkg/util/helpers.go).

By keeping application logic out of `/cmd`, you enable reuse in other programs, simplify testing without binary invocation, and maintain clear architectural boundaries.

## Complete Project Layout Example

The following structure demonstrates a minimal yet complete implementation following the `golang-standards/project-layout` conventions:

```

project/
├─ cmd/
│  └─ myapp/
│     └─ main.go            <-- thin wrapper
├─ internal/
│  └─ app/
│     └─ service.go        <-- private business logic
└─ pkg/
   └─ util/
      └─ helpers.go        <-- reusable utilities

```

### cmd/myapp/main.go

The entry-point delegates all work to imported packages:

```go
package main

import (
	"log"

	"github.com/yourusername/project/internal/app"
	"github.com/yourusername/project/pkg/util"
)

func main() {
	// Initialize reusable utilities
	if err := util.Setup(); err != nil {
		log.Fatalf("setup failed: %v", err)
	}

	// Run the core service (private code)
	if err := app.Run(); err != nil {
		log.Fatalf("service error: %v", err)
	}
}

```

### internal/app/service.go

Contains the main application logic, protected from external import:

```go
package app

import "fmt"

// Run contains the main application logic.
// It is private to this repository.
func Run() error {
	fmt.Println("Hello from the internal service!")
	// ... more business logic ...
	return nil
}

```

### pkg/util/helpers.go

Provides reusable utilities that external projects may import:

```go
package util

import "fmt"

// Setup provides a reusable helper that can be imported by any project.
func Setup() error {
	fmt.Println("Utility setup complete.")
	return nil
}

```

## Building Executables from /cmd

To compile the binary while preserving the project structure, specify the path to the subdirectory containing [`main.go`](https://github.com/golang-standards/project-layout/blob/main/main.go):

```bash
go build -o bin/myapp ./cmd/myapp

```

Executing `bin/myapp` produces:

```

Utility setup complete.
Hello from the internal service!

```

This approach ensures that `go build` treats `cmd/myapp` as a command package, creating a standalone executable while keeping your workspace organized.

## Summary

- The `/cmd` directory contains executable entry-points, with each subdirectory named after the target binary
- [`main.go`](https://github.com/golang-standards/project-layout/blob/main/main.go) files should remain thin wrappers that import logic from `/internal` and `/pkg`
- Use `/internal` for private code that the Go compiler protects from external import
- Use `/pkg` for public libraries intended for reuse across projects
- Build specific binaries using `go build ./cmd/<binary-name>`

## Frequently Asked Questions

### What belongs inside the /cmd directory versus the /pkg directory?

The `/cmd` directory should contain only `main` packages and minimal wiring code required to start an application. All reusable business logic, domain models, and service implementations belong in `/internal` (if private) or `/pkg` (if public). This separation ensures that your executables remain lightweight and that core logic can be tested independently without invoking a binary.

### Can I have multiple binaries in a single Go project?

Yes. The `golang-standards/project-layout` explicitly supports multiple binaries by placing each in its own subdirectory under `/cmd`. For example, you might have `cmd/server` for a daemon process and `cmd/migrate` for database migrations. Each subdirectory contains its own [`main.go`](https://github.com/golang-standards/project-layout/blob/main/main.go) and builds independently using `go build ./cmd/server` or `go build ./cmd/migrate`.

### How does the /internal directory enforce privacy?

Go's compiler recognizes the `internal` directory as a special path. Code within `internal/` and its subdirectories can only be imported by packages rooted at the parent of the `internal` directory. For instance, code in `project/internal/app/` can be imported by `project/cmd/myapp` but not by an external repository, preventing accidental coupling to your implementation details.

### Should I place all my main.go files directly in /cmd or in subdirectories?

Always place [`main.go`](https://github.com/golang-standards/project-layout/blob/main/main.go) files inside subdirectories named after the desired binary. The `/cmd` directory itself should not contain Go source files directly. Following `cmd/<binary-name>/main.go` ensures that `go build` produces correctly named executables and maintains clarity about which code produces which binary.