Help us shape the future of Go! Take the 2026 Go Developer Survey

gobinignore

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 9 Imported by: 0

README

GitHub Workflow Status (branch) GoDoc Coverage Status Supported Go Versions GitHub Release Go Report Card

gobinignore

Put an in-place .gitignore into each main package so the loose executable a careless go build leaves behind stays out of git.


CHINESE README

中文说明

AI Agents

This repo helps keep build output out of git. Within a Go repo, each main package (has package main + func main) should hold its own .gitignore with one anchored line /<name> — the executable go build drops there. To scan / write: run gobinignore -path <repo> (report), then gobinignore -path <repo> -edit (write). Do not pile path-scoped one-offs into a parent/root .gitignore.

Main Features

🎯 Precise, in-place: each main package gets its own .gitignore with an anchored /name line — no globs, no cross-path surprises.

⚡ Two modes: report on its own (a CI gate); -edit writes the missing files.

🧠 Exact detection: parses package main + func main via go/ast, not a naive grep.

🧩 One repo, three faces: import the Go package, run the CLI, let Claude use the plugin.


Installation

# CLI
go install github.com/yylego/gobinignore/cmd/gobinignore@latest
# Go package
go get github.com/yylego/gobinignore

The problem

The standard Go .gitignore catches just the suffixed executables (*.exe, *.so, *.dylib, *.test). But when you run go build inside a main package, the executable it drops takes the package name and has no suffix — so the standard template misses it. It lands in git status, and one careless git add bakes it into the git log (a bloated repo, a dreaded cleanup, the works).

The rule

Where an artifact is produced, ignore it right there. Each main package (has package main + func main) gets a .gitignore inside itself, with a single anchored line: / + the executable name (a leading slash pins it to that package; a bare name is a glob that also snags same-named nested paths). Do not pile path-scoped one-offs into a parent/root .gitignore — that pollutes the shared rule, needs upkeep as directories come and go, and rots the moment someone renames that path but misses the second one. A single in-place line is the one source of truth: it lives beside the code, moves with it, renames with it.

Usage

# report, no changes (default; exits non-zero if a fix is needed)
gobinignore -path <repo>
# write the missing in-place .gitignore files
gobinignore -path <repo> -edit

How it decides what to touch

It computes each in-place executable path, then asks git check-ignore if that path is ignored:

  • ignored via its own in-place .gitignore → compliant, left as is.
  • ignored via a parent/root path-scoped rule (e.g. /cmd/app/app) → the pile-up anti-pattern; -edit adds the in-place one and asks you to remove the parent line.
  • ignored via a rule that hides the entire tree (e.g. bin/) → covered, left as is.
  • not caught anywhere → needs an in-place .gitignore; -edit adds it.

It skips generated/vendored trees such as .git and node_modules.

As a Claude Code plugin

This repo doubles as a plugin marketplace, so Claude Code can run the scan and add the missing ignores on demand:

/plugin marketplace add yylego/gobinignore
/plugin install yylego-gobinignore@gobinignore

The bundled plugin knows the rule and runs the CLI at the right moments.

Use as a Go package

Import the package to scan / write in code:

import "github.com/yylego/gobinignore"

res, err := gobinignore.Scan(".")
// handle err, then:
for _, f := range res.Findings {
	if f.NeedsFix() {
		gobinignore.Edit(f) // writes the anchored /name line
	}
}

📄 License

MIT License - see LICENSE.


💬 Contact & Feedback

Contributions are welcome! Report bugs, suggest features, and contribute code:

  • 🐛 Mistake reports? Open an issue on GitHub with reproduction steps
  • 💡 Fresh ideas? Create an issue to discuss
  • 📖 Documentation confusing? Report it so we can improve
  • 🚀 Need new features? Share the use cases to help us understand requirements
  • ⚡ Performance issue? Help us optimize through reporting slow operations
  • 🔧 Configuration problem? Ask questions about complex setups
  • 📢 Follow project progress? Watch the repo to get new releases and features
  • 🌟 Success stories? Share how this package improved the workflow
  • 💬 Feedback? We welcome suggestions and comments

🔧 Development

New code contributions, follow this process:

  1. Fork: Fork the repo on GitHub (using the webpage UI).
  2. Clone: Clone the forked project (git clone https://github.com/yourname/repo-name.git).
  3. Navigate: Navigate to the cloned project (cd repo-name)
  4. Branch: Create a feature branch (git checkout -b feature/xxx).
  5. Code: Implement the changes with comprehensive tests
  6. Testing: (Golang project) Ensure tests pass (go test ./...) and follow Go code style conventions
  7. Documentation: Update documentation to support client-facing changes
  8. Stage: Stage changes (git add .)
  9. Commit: Commit changes (git commit -m "Add feature xxx") ensuring backward compatible code
  10. Push: Push to the branch (git push origin feature/xxx).
  11. PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.

Please ensure tests pass and include relevant documentation updates.


🌟 Support

Welcome to contribute to this project via submitting merge requests and reporting issues.

Project Support:

  • ⭐ Give GitHub stars if this project helps you
  • 🤝 Share with teammates and (golang) programming friends
  • 📝 Write tech blogs about development tools and workflows - we provide content writing support
  • 🌟 Join the ecosystem - committed to supporting open source and the (golang) development scene

Have Fun Coding with this package! 🎉🎉🎉

GitHub Stars

Stargazers

Documentation

Overview

Package gobinignore 找出仓库里"主包 + 主函数"的目录,给缺就近 .gitignore 的 补上精确锚定的一行,挡住会被就地 go build 出来的同名无后缀可执行文件。

库只负责【判定】与【写入】,不打印、不决定进程退出码——那些交给调用方(见 cmd)。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Edit

func Edit(f Finding) error

Edit 给需要修的目录(NeedsIgnore / PileUp)写入就近的 /二进制名; 对 HasIgnore / Covered 是空操作。

Types

type Finding

type Finding struct {
	Dir     string // 目录绝对路径
	Bin     string // 就地 build 产出的二进制名 = filepath.Base(Dir)
	State   State
	Source  string // 仅 PileUp:命中规则的来源 .gitignore(相对仓库根)
	Pattern string // 仅 PileUp:命中的 pattern
}

Finding 是一个"主包 + 主函数"目录及其就地二进制的忽略状况。 Dir 是绝对路径;要展示相对仓库根的路径,调用方拿 Result.Repo 自己算 filepath.Rel。

func (Finding) NeedsFix

func (f Finding) NeedsFix() bool

NeedsFix 表示这个目录需要补就近 .gitignore(缺失或反模式)。

type Result

type Result struct {
	Repo     string    // git 仓库根(绝对路径)
	Findings []Finding // 每个主包目录一条,按路径排序
}

Result 是一次扫描的结果。

func Scan

func Scan(path string) (*Result, error)

Scan 找出 path 子树里所有"主包 + 主函数"目录(path 须在 git 仓库内), 逐个判定其就地二进制的忽略状况。不改动任何文件。

type State

type State int

State 是一个主包目录"就地二进制忽略状况"的分类。

const (
	// NeedsIgnore:没有任何规则挡住这个二进制 —— 需要补就近 .gitignore。
	NeedsIgnore State = iota
	// HasIgnore:已被它自己的就近 .gitignore 挡住 —— 合规。
	HasIgnore
	// PileUp:只被父/根里 path-scoped 的规则点名兜住 —— 反模式。
	PileUp
	// Covered:被整目录/上层广义规则(如 bin/)兜住 —— 不用管。
	Covered
)

Directories

Path Synopsis
cmd
gobinignore command
Command gobinignore 给每个"主包 + 主函数"目录补一个精确锚定的就近 .gitignore, 挡住会被就地 go build 出来、跟目录同名且无后缀的可执行文件,防止它漏进 git。
Command gobinignore 给每个"主包 + 主函数"目录补一个精确锚定的就近 .gitignore, 挡住会被就地 go build 出来、跟目录同名且无后缀的可执行文件,防止它漏进 git。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL