go-client-template

CircleCI Stability: Active

đź§° bin

Shared executables, Makefile includes, and agent skills for projects that use this repository as a Git submodule at ./bin.

🎯 Why This Exists

The projects that use this repository share the same build, lint, test, security, Docker, release, and agent-workflow glue. Keeping that glue here makes the consuming repositories smaller while giving them one supported integration path.

🚀 Install Or Bootstrap

Add this repository as the downstream project’s bin submodule:

git submodule add git@github.com:alexfalkowski/bin.git bin
git submodule update --init

[!IMPORTANT] In a fresh checkout of a project that already has the submodule, initialize it before using targets supplied by bin.

git submodule update --init

đź’» Usage

Include only the Make fragments your project needs. The fragments derive helper paths from their own location, so downstream includes work when this repository is mounted at ./bin. Inside this repository, the root Makefile includes the same fragments from build/make/.

For command discovery, include help.mak and run make or make help in the consuming repository.

include bin/build/make/help.mak
include bin/build/make/go.mak

Go alignment targets require betteralign in PATH, with support for -test_files and -fix. Both make field-alignment and make fix-field-alignment use betteralign -test_files to check or fix named structs in Go source and test files; fixes preserve comments. lint and fix-lint include these targets. The service fragments provide the same alignment coverage through go-lint and go-fix-lint.

The optional .gofa file selects comma-separated package paths relative to the project root, for example internal/foo,internal/bar. Each becomes ./<path>/...; a missing or empty file defaults to ./....

Alignment checks and fixes skip generated files and anonymous structs, including nested anonymous struct fields and struct literals. Generated layouts remain under the generator’s control. This intentionally narrows the previous fieldalignment check coverage; skipped layouts are neither reported nor fixed.

Ruby projects typically include the Ruby fragment instead:

include bin/build/make/help.mak
include bin/build/make/ruby.mak

Projects that use the shared git workflow can include it separately:

include bin/build/make/git.mak

Git Worktrees

The git fragment can create local worktrees for independently checked-out feature branches. Keep the primary checkout on master, then create and work from a sibling directory:

make add-feature-worktree name=login worktree=../app-login
cd ../app-login
make review msg="add login flow" desc="..."

This fetches origin, creates a branch named <username>-<random>/feat/login from origin/master, and initializes submodules in the new worktree. add-worktree is also available when you need to provide a branch prefix directly:

make add-worktree branch=fix/login worktree=../app-login-fix

The shared commit, amend, and edit-amend targets stage changes but refuse to commit on master; create a branch first. The force, review, and ready flows use these targets too.

List and remove worktrees from the primary checkout. Removal refuses a dirty worktree and does not delete its branch:

make list-worktrees
make remove-worktree worktree=../app-login
make prune-worktrees

Consuming repositories choose which fragments to include and remain responsible for project-specific configuration such as service code, image names, release version files, and environment-specific settings.

🤖 Agent Skills

This repository also ships shared agent guidance in skills/. Each skill is a skills/<name>/SKILL.md file that works with both OpenAI Codex and Claude Code; skills/<name>/agents/openai.yaml carries the Codex-specific interface and invocation policy.

Skills support natural-language selection by default. review-pr keeps that behavior for explicit requests such as prepare a review PR from these local changes, as well as $review-pr in Codex or /review-pr in Claude Code. Those requests run its review, validation, commit, force-push, and draft-PR workflow; asking only for a code review authorizes the review. See the review-pr skill for its authorization gates.

Skill maintainers must keep invocation settings consistent across assistants:

Selection mode Claude Code disable-model-invocation Codex policy.allow_implicit_invocation
Natural-language selection (default) false or omitted true or omitted
Named invocation only true false

These settings control discovery; the skill instructions and AGENTS.md define task authorization. make skills-lint checks the boolean values and agreement between the two settings. Field behavior is documented in the official Claude Code skill docs and OpenAI skill docs.

Codex

Codex discovers repository skills from .agents/skills, so wire a downstream repository once with the shared bootstrap, then commit the result:

include bin/build/make/codex.mak
make codex-init

This creates a .agents/skills symlink to bin/skills, a .codex/config.toml symlink to the shared permission profile in bin/build/codex/config.toml, and a .codex/rules/bin.rules symlink to the shared execution guardrails. A repository-owned real config or rule file is left untouched. Every later clone can invoke shared skills with $, for example $code-review, and receives the shared permissions after the one-time project trust prompt. Repositories with an existing real config can merge the shared settings explicitly.

The permission profile requires Codex 0.138.0 or later. It confines routine commands to the workspace while making workspace Git metadata and the standard Go, RuboCop, golangci-lint, and Trivy caches writable. It grants read access to common host credential locations, permits outbound network access, and allows writes to standard system temporary directories. Every make invocation runs outside the sandbox without prompting, except make pr, make draft, make merge, make ready, and make review, which stay approval-gated because they create, merge, or force-push a pull request. Direct cleanup inside writable sandbox roots is allowed, direct recognized remote and external-system changes require approval, and catastrophic commands are forbidden. Root .env and .env.* files remain protected, while nested dependency environment files and .envrc files are allowed for native dependency workflows. The active agent configuration provides runtime approval guardrails; AGENTS.md continues to define task scope and workflow authorization.

[!WARNING] The shared profile is only for trusted repositories. Make targets run outside the sandbox and inherit the user’s host access, while sandboxed commands can read configured credentials and send data over the internet. Review executable repository content, Makefiles, and dependency scripts before using it.

Legacy sandbox_mode settings and the --sandbox CLI flag take precedence over permission profiles. Remove those overrides when the shared profile should be active.

Codex loads project config and rules only for trusted repositories. Put per-machine additions in ~/.codex/config.toml and ~/.codex/rules/default.rules; Codex also records accepted persistent command prefixes in that user rules file. Re-run make codex-init only when the shared paths move. Updates to the shared profile or rules propagate with the next bin submodule update; fully restart the Codex CLI process afterward, since Codex loads rules at process startup and a new session or prompt within an already-running process does not pick up the change.

Codex reads AGENTS.md separately for repository instructions. Downstream repositories should still point agents at the shared instructions instead of copying the skill list:

## Shared guidance

Use `bin/AGENTS.md` for shared skills and cross-repository defaults.

Claude Code

Claude Code does not scan submodules; it only loads skills from .claude/skills/ and instructions from CLAUDE.md. Wire a repository once with the shared bootstrap, then commit the results:

include bin/build/make/claude.mak
make claude-init

This creates a .claude/skills symlink to bin/skills, a .claude/settings.json symlink to the shared permissions baseline in bin/build/claude/settings.json (unless the repository owns a real, non-symlink settings.json), and a managed block in CLAUDE.md that imports the local and shared AGENTS.md. All are committed, so every later clone works with no per-machine setup beyond the one-time workspace trust prompt. Invoke a skill as a slash command, for example /code-review. Re-run make claude-init only when the shared skills directory moves; adding a new skill or updating the permissions baseline needs no downstream change because the symlinks target shared paths that follow bin.

The baseline starts in Claude Code’s default permission mode, enables the Bash sandbox, and routes direct Bash commands through the permissions allow, ask, and deny guardrails. Direct Bash is broadly allowed without prompting while it remains sandboxed; project-local operations stay autonomous, recognized remote and external-system changes require approval, and catastrophic commands are forbidden. The unsandboxed escape hatch is disabled. The sandbox grants write access to the workspace, the standard Go, RuboCop, golangci-lint, and Trivy caches used by project commands, and standard system temporary directories. This means an allowed Bash redirect, sed -i, rm, or similar command can mutate workspace files without an Edit prompt; use this baseline only in trusted repositories and prefer diff-reviewable edits where practical. Every make invocation is excluded from the sandbox and allowed without prompting, except make pr, make draft, make merge, make ready, and make review, which require approval because they create, merge, or force-push a pull request. Built-in file edits stay scoped to the workspace, and the active agent configuration provides runtime approval guardrails while AGENTS.md defines task scope and workflow authorization.

Permission-baseline updates propagate with the next bin submodule update; fully restart the Claude Code process afterward, since settings.json is read at process startup and a new conversation within an already-running process does not pick up the change.

[!WARNING] The shared baseline is only for trusted repositories. Make targets run outside the sandbox and inherit the user’s host access. The Bash sandbox permits broad reads and configured cache writes, and it does not impose blanket secret-read restrictions. Review executable repository content, Makefiles, and dependency scripts before using it.

Put per-repository or per-machine permission tweaks in the gitignored .claude/settings.local.json, which Claude Code merges over the baseline. Wiring the *-template repositories once pre-wires every repository generated from them.

Update AGENTS.md when the shared skill set, composition rules, or repository workflow guidance changes.

🛠️ Operations

This repository is shared tooling. Changes can affect every downstream project that vendors it, so prefer small compatible changes and validate through the repository Make targets.

Some helpers intentionally depend on tools or services outside this repository: Docker helpers assume the consuming project supplies image names and release version files; the shared Go Dockerfile uses Dockerfile.dockerignore next to the Dockerfile, which takes precedence over a consuming repository’s root .dockerignore; security helpers assume Trivy is available; shell and Dockerfile lint targets depend on shellcheck and hadolint; build/docker/env pulls, rebases, and updates submodules in an existing sibling ../docker checkout, or uses SSH to clone git@github.com:alexfalkowski/docker.git there when missing.

make manifest-docker requires Docker Buildx and jq. It reads the release version from APP_VERSION_FILE (default /tmp/workspace/release-version.txt) and does nothing when that file is absent. An existing version must contain exactly the intended linux/amd64 and linux/arm64 child digests and platforms; matching versions are left in place and latest is still published. Conflicts and inspection failures stop publication. Recognized transient registry failures use at most three attempts with exponential backoff and jitter; permission and content errors are not retried. Both tags use the verified child digests, and a version push that fails transiently is inspected again before another push.

đź”— References