Skip to content

Commit de52ef2

Browse files
authored
docs: public docs (#54)
1 parent e052dbd commit de52ef2

33 files changed

Lines changed: 21057 additions & 5 deletions

‎README.md‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Freight 🚂
2+
3+
[![Go Version](https://img.shields.io/github/go-mod/go-version/devbytes-cloud/freight)](https://go.dev/)
4+
[![License](https://img.shields.io/github/license/devbytes-cloud/freight)](https://opensource.org/licenses/BSD-3-Clause)
5+
6+
**The professional, zero-dependency Git hook manager for modern teams.**
7+
8+
Read the full documentation at [freightapp.co](https://freightapp.co).
9+
10+
Freight streamlines Git workflows by rewiring every Git hook in your repository to a single **Conductor** binary. All logic is defined in a declarative **Railcar** manifest (`railcar.json`), ensuring your hooks are portable, fast, and easy to manage.
11+
12+
## Why Freight?
13+
14+
### 🚀 Zero Runtime Dependencies
15+
Unlike Husky (which requires Node.js) or pre-commit (which requires Python), Freight is a single, static Go binary. Your developers don't need to install a specific runtime just to run Git hooks.
16+
17+
### 📦 Unified Configuration
18+
Manage every hook—from `pre-commit` to `post-merge`—in one `railcar.json` manifest. No more messy `.git/hooks` directory filled with ad-hoc scripts.
19+
20+
### 🛠️ Built for Portability
21+
Freight's 'Conductor/Railcar' architecture ensures that your hooks work identically across Windows, macOS, and Linux.
22+
23+
### 🥊 Freight vs. Husky
24+
| Feature | Freight | Husky |
25+
|---------|---------|-------|
26+
| **Runtime** | None (Static Binary) | Node.js |
27+
| **Setup** | `freight init` | `npm install` |
28+
| **Config** | Single JSON file | Multiple files/package.json |
29+
| **Portability** | High (Binary included) | Moderate (Requires Node) |
30+
31+
---
32+
33+
## Quick Start
34+
35+
### 1. Install
36+
- **Homebrew (macOS):** `brew install --cask devbytes-cloud/tap/freight`
37+
- **Precompiled Binaries:** `[GitHub Releases](https://github.com/devbytes-cloud/freight/releases)`
38+
39+
### 2. Setup
40+
Run the following command in your Git repository:
41+
```bash
42+
freight init
43+
```
44+
This installs the **Conductor** binary and creates a starter **Railcar** manifest (`railcar.json`).
45+
46+
### 3. Verify
47+
Add a script to your `railcar.json` and watch it run on your next commit!
48+
49+
---
50+
51+
## Architecture: Conductor & Railcar
52+
53+
Freight operates on a simple, powerful metaphor:
54+
- **The Conductor:** A tiny, high-performance binary placed at your repo root. It is the single entry point for all Git hooks.
55+
- **The Railcar:** A `railcar.json` manifest that defines exactly what the Conductor should execute for each hook.
56+
57+
When a Git hook fires, the Conductor extracts the logic from the Railcar and executes it with precision.
58+
59+
---
60+
61+
## Documentation
62+
63+
For full documentation, recipes, and advanced configuration, visit [freightapp.co](https://freightapp.co).
64+
65+
## License
66+
67+
MIT. See `LICENSE` for full text.

‎cmd/conductor/main.go‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ func main() {
4545
if err != nil {
4646
pterm.Fatal.Println("Error reading commit message file: ", err)
4747
}
48-
49-
// Process the commit message
5048
if len(cfg.RailCar.CommitOperations.CommitMsg) != 0 {
5149
run(cfg.RailCar.CommitOperations.CommitMsg, string(commitMsg))
5250
}

‎internal/commands/root.go‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@ func Execute() {
2626
// NewRootCmd creates and returns the root command for the CLI application.
2727
func NewRootCmd() *cobra.Command {
2828
rootCmd := &cobra.Command{
29+
Use: "freight",
30+
Short: "Freight is a zero-dependency Git hook manager.",
31+
Long: `Freight is a zero-dependency Git hook manager built in Go. It uses a Conductor binary and a Railcar manifest to manage Git hooks across your project.`,
32+
}
33+
34+
initCmd := &cobra.Command{
2935
Use: "init",
30-
Short: "init",
31-
Long: `init`,
36+
Short: "Initialize Freight in the current repository",
37+
Long: `Initialize Freight by installing the Conductor binary, creating a starter Railcar manifest (railcar.json), and rewiring Git hooks.`,
3238
Run: func(cmd *cobra.Command, args []string) {
3339
if err := validate.GitDirs(); err != nil {
3440
cmd.PrintErrln(err)
@@ -51,7 +57,8 @@ func NewRootCmd() *cobra.Command {
5157
},
5258
}
5359

54-
rootCmd.Flags().BoolP("config-force", "c", false, "If you wish to force write the config")
60+
initCmd.Flags().BoolP("config-force", "c", false, "If you wish to force write the config")
61+
rootCmd.AddCommand(initCmd)
5562

5663
return rootCmd
5764
}

‎temp_backup/images/freight.jpg‎

124 KB
Loading

‎temp_backup/images/freight.png‎

115 KB
Loading

‎temp_backup/readme.md‎

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
# Freight
2+
3+
## Project Overview
4+
5+
Freight is a Go-based CLI tool that streamlines Git workflows by rewiring every Git hook in your repository to call a
6+
single binary named `conductor` (placed at the repo root).`conductor` reads a JSON configuration file (`railcar.json`)
7+
that lists the shell commands you want to run for each
8+
hook. All logic therefore lives in one easy-to-version file instead of a dozen ad-hoc hook scripts.
9+
10+
---
11+
12+
## Features
13+
14+
* **One-step hook bootstrap** – `freight init` installs `conductor`, generates `railcar.json`, and rewrites every Git
15+
hook in one go.
16+
* **Declarative configuration** – add, remove, or reorder hook commands by editing JSON.
17+
* **Cross-platform binaries** – pre-built for Linux, macOS, and Windows.
18+
* **Positional-argument support** – hooks such as `commit-msg` or `pre-push` automatically pass their arguments to your
19+
commands (via `${HOOK_INPUT}`).
20+
* **Zero vendor lock-in** – all generated files live inside your repo; deleting them restores the default Git behaviour.
21+
22+
---
23+
24+
## Installation
25+
26+
### From Source
27+
28+
```
29+
git clone https://github.com/devbytes-cloud/freight.git
30+
cd freight
31+
go mod tidy
32+
make build-all
33+
```
34+
35+
---
36+
37+
## Quick Start
38+
39+
```
40+
# Inside any existing Git repository
41+
freight init # installs conductor + railcar.json + rewired hooks
42+
git add . && git commit -m "test" # your new hooks will now fire
43+
```
44+
45+
Need to overwrite an existing `railcar.json`?
46+
`freight init --config-force`
47+
48+
---
49+
50+
## Command-line Reference
51+
52+
| Command | Description |
53+
|----------------|---------------------------------------------|
54+
| `freight init` | Bootstrap Freight in the current repository |
55+
| `freight help` | Show global or command-specific help |
56+
57+
Global flags:
58+
59+
* `-c, --config-force` – overwrite an existing `railcar.json`
60+
* `-h, --help` – display help
61+
62+
---
63+
64+
## How It Works (under the hood)
65+
66+
1. **Bootstrap (`freight init`)**
67+
* Places a self-contained `conductor` binary at your repo root.
68+
* Generates a starter `railcar.json`.
69+
* Replaces every file in `.git/hooks/` with a tiny wrapper script that simply executes `conductor` with the hook
70+
name and original arguments.
71+
72+
2. **Hook trigger** – Git fires `pre-commit`, `commit-msg`, etc.
73+
* The wrapper calls `conductor`.
74+
* `conductor` loads `railcar.json`, finds the matching section, and runs each configured action.
75+
* Any non-zero exit in a pre-hook aborts the Git operation.
76+
77+
---
78+
79+
## `railcar.json` Syntax
80+
81+
Hierarchical structure
82+
83+
* **config** – top level
84+
* **\<operation-family\>** – e.g. `commit-operations`, `checkout-operations`
85+
* **\<git-hook\>** – e.g. `pre-commit`, `commit-msg`, `post-checkout`
86+
* **actions array** – each item needs:
87+
* `name` – label for readability
88+
* `command` – shell snippet to run
89+
90+
Example starter file:
91+
92+
```
93+
{
94+
"config": {
95+
"commit-operations": {
96+
"pre-commit": [
97+
{ "name": "echo", "command": "echo conductor is running!" }
98+
],
99+
"prepare-commit-msg": [],
100+
"commit-msg": [],
101+
"post-commit": []
102+
},
103+
"checkout-operations": {
104+
"post-checkout": []
105+
}
106+
}
107+
}
108+
```
109+
110+
### Referencing Hook Arguments
111+
112+
Hooks that receive parameters expose them in two interchangeable ways:
113+
114+
| Placeholder | Meaning (example: `commit-msg`) |
115+
|-----------------|---------------------------------|
116+
| `${HOOK_INPUT}` | Alias for the parameter (`$1`) |
117+
118+
Use whichever style you prefer:
119+
120+
```
121+
{
122+
"commit-msg": [
123+
{ "name": "validate", "command": "grep -E '^(feat|fix): ' ${HOOK_INPUT}" },
124+
{ "name": "print", "command": "echo 'MSG file → ${HOOK_INPUT}'" }
125+
]
126+
}
127+
```
128+
129+
### Real-world Examples
130+
131+
* Run tests before committing
132+
133+
```
134+
{
135+
"pre-commit": [
136+
{ "name": "tests", "command": "go test ./..." }
137+
]
138+
}
139+
```
140+
141+
* Enforce Conventional Commits format
142+
143+
```
144+
{
145+
"commit-msg": [
146+
{ "name": "conventional", "command": "npx commitlint --edit $1" }
147+
]
148+
}
149+
```
150+
151+
* Verify tags before pushing
152+
153+
```
154+
{
155+
"pre-push": [
156+
{ "name": "verify-tags", "command": "./scripts/check_tags.sh $@" }
157+
]
158+
}
159+
```
160+
161+
Notes
162+
163+
* **Order** – actions execute sequentially in array order.
164+
* **Shell chaining** – combine commands (`go vet ./... && go test ./...`).
165+
* **Environment vars** – standard shell expansion works (`FOO=bar ./script.sh`).
166+
* **Idempotency** – `freight init` never overwrites `railcar.json` unless `--config-force` is supplied.
167+
168+
---
169+
170+
## Supported Git Hooks & Execution Order
171+
172+
```
173+
Commit : pre-commit → prepare-commit-msg → commit-msg → post-commit
174+
Merge : pre-merge-commit → post-merge
175+
Rebase : pre-rebase → post-rewrite
176+
Push : pre-push → update → post-update → post-receive
177+
Checkout : pre-checkout → post-checkout
178+
ApplyPatch : applypatch-msg → pre-applypatch → post-applypatch
179+
```
180+
181+
---
182+
183+
## Troubleshooting
184+
185+
| Issue | Fix |
186+
|------------------------------|-----------------------------------------------------------------------------------|
187+
| Permission denied on hooks | `chmod +x ./conductor` (and ensure hooks are executable) |
188+
| Hook seems to do nothing | Check `.git/hooks/<hook>` – it should contain the wrapper that calls `conductor`. |
189+
| Command not found | Ensure the command exists in `$PATH` or use an absolute path in `railcar.json`. |
190+
| Need to debug a failing hook | Run the failing hook script manually or add `set -x` inside your action command. |
191+
192+
---
193+
194+
## Contributing
195+
196+
```
197+
git clone https://github.com/yourusername/freight.git
198+
git checkout -b my-feature
199+
# make changes
200+
git commit -s -m "feat: awesome contribution"
201+
git push origin my-feature
202+
```
203+
204+
Open a Pull Request—thank you!
205+
206+
### Build & Release
207+
208+
### 1. Release & Distribution (GoReleaser + ) `go:embed`
209+
210+
- The repository contains a that builds **platform-specific `conductor` binaries** for Linux, macOS and Windows (amd64,
211+
arm, arm64). `.goreleaser.yaml`
212+
- These binaries are dropped into `assets/dist/` and then **embedded directly into the main `freight` executable** via
213+
Go’s mechanism (). `//go:embed``assets/embed.go`
214+
- At runtime, `freight init` extracts the correct pre-built `conductor` for the user’s OS/CPU.
215+
- CGO is disabled () so binaries are fully statically linked and portable. `CGO_ENABLED=0`
216+
217+
### 2. Hook-Generation Template
218+
219+
- Git hooks are produced from a **single script template** (`internal/githooks/gitHookTemplate`) so every generated hook
220+
is tiny, consistent, and easy to audit.
221+
- Unit tests in verify that every hook file is generated with the expected path and template. `githooks_test.go`
222+
223+
A short note in the README can highlight the attention to reliability and test coverage.
224+
225+
### 3. Testing
226+
227+
- The project ships with a Go test suite () that covers hook generation, path handling, and validation helpers.
228+
`go test ./...`
229+
- Mentioning this encourages contributors to run tests before submitting pull requests.
230+
231+
### 4. Make Targets
232+
233+
- If you already have a , consider listing other useful targets (`make test`, `make lint`, etc.) so newcomers can find
234+
them quickly. `make build-all`
235+
236+
---
237+
238+
## License
239+
240+
BSD-style. See `LICENSE` for full text.
241+
railcar.json
242+
243+
# Docusaurus
244+
website/node_modules
245+
website/.docusaurus
246+
website/build
247+
website/.cache

‎website/.gitignore‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Dependencies
2+
/node_modules
3+
4+
# Production
5+
/build
6+
7+
# Generated files
8+
.docusaurus
9+
.cache-loader
10+
11+
# Misc
12+
.DS_Store
13+
.env.local
14+
.env.development.local
15+
.env.test.local
16+
.env.production.local
17+
18+
npm-debug.log*
19+
yarn-debug.log*
20+
yarn-error.log*

0 commit comments

Comments
 (0)