@@ -73,11 +73,12 @@ Available Commands:
7373
7474
7575Flags:
76- -d, --dryrun dry run, output to stdout (ignores quiet)
77- -h, --help help for txeh
78- -q, --quiet no output
79- -r, --read string (override) Path to read /etc/hosts file.
80- -w, --write string (override) Path to write /etc/hosts file.
76+ -d, --dryrun dry run, output to stdout (ignores quiet)
77+ -h, --help help for txeh
78+ -m, --max-hosts-per-line int Max hostnames per line (0=auto, -1=unlimited, >0=explicit)
79+ -q, --quiet no output
80+ -r, --read string (override) Path to read /etc/hosts file.
81+ -w, --write string (override) Path to write /etc/hosts file.
8182```
8283
8384
@@ -120,6 +121,91 @@ txeh add 127.1.27.100 dev3.example.com -r ./hosts.test -w ./hosts.test2
120121
121122```
122123
124+ ## Comments
125+
126+ txeh supports inline comments on host entries, useful for tracking which tool or purpose added specific entries (e.g., docker, development environments).
127+
128+ ### How Comments Work
129+
130+ Comments use the standard hosts file format: `IP HOSTNAME [HOSTNAME...] # comment`
131+
132+ **Key behavior:**
133+ - Comments are used for **grouping**: hosts with the same IP AND same comment are placed on the same line
134+ - Hosts added **without** a comment only match lines **without** a comment
135+ - Hosts added **with** a comment only match lines **with the same comment**
136+ - Comments are **never modified** on existing lines
137+ - If no matching line exists, a new line is created
138+
139+ ### CLI Usage
140+
141+ ```bash
142+ # Add host with a comment
143+ sudo txeh add 127.0.0.1 myapp --comment "local development"
144+ # Result: 127.0.0.1 myapp # local development
145+
146+ # Add another host with the same comment (groups together)
147+ sudo txeh add 127.0.0.1 myapp2 --comment "local development"
148+ # Result: 127.0.0.1 myapp myapp2 # local development
149+
150+ # Add host with a different comment (new line)
151+ sudo txeh add 127.0.0.1 api --comment "staging environment"
152+ # Result: 127.0.0.1 api # staging environment
153+
154+ # Add host without a comment (only matches lines without comments)
155+ sudo txeh add 127.0.0.1 test
156+ # Result: goes to first 127.0.0.1 line that has NO comment, or creates new line
157+ ```
158+
159+ ### Library Usage
160+
161+ ```go
162+ // Add hosts with a comment
163+ hosts.AddHostWithComment("127.0.0.1", "myapp", "local development")
164+ hosts.AddHostsWithComment("127.0.0.1", []string{"svc1", "svc2"}, "my project services")
165+
166+ // Add hosts without a comment (original behavior)
167+ hosts.AddHost("127.0.0.1", "myhost")
168+ hosts.AddHosts("127.0.0.1", []string{"a", "b", "c"})
169+ ```
170+
171+ ### Example Scenario
172+
173+ Starting hosts file:
174+ ```
175+ 127.0.0.1 localhost
176+ 127.0.0.1 app1 app2 # dev services
177+ ```
178+
179+ | Command | Result |
180+ |---------|--------|
181+ | `txeh add 127.0.0.1 app3 -c "dev services"` | app3 added to "dev services" line |
182+ | `txeh add 127.0.0.1 api -c "staging env"` | New line: `127.0.0.1 api # staging env` |
183+ | `txeh add 127.0.0.1 test` | test added to localhost line (no comment) |
184+
185+ ### Listing and Removing by Comment
186+
187+ List all hosts with a specific comment:
188+ ```bash
189+ sudo txeh list bycomment "dev services"
190+ ```
191+
192+ Remove all entries with a specific comment (removes entire lines):
193+ ```bash
194+ sudo txeh remove bycomment "dev services"
195+ ```
196+
197+ ### Modifying Comments
198+
199+ Comments are never modified on existing lines. To change a comment, remove the hosts first and re-add them with the new comment:
200+
201+ ```bash
202+ # Remove all entries with the old comment
203+ sudo txeh remove bycomment "old comment"
204+
205+ # Re-add with the new comment
206+ sudo txeh add 127.0.0.1 app1 app2 --comment "new comment"
207+ ```
208+
123209## txeh Go Library
124210
125211**Dependency:**
@@ -129,50 +215,66 @@ go get github.com/txn2/txeh
129215
130216**Example Golang Implementation**:
131217```go
132-
133218package main
134219
135220import (
136221 "fmt"
137- "strings"
138222
139223 "github.com/txn2/txeh"
140224)
141225
142226func main() {
227+ // Load the system hosts file
143228 hosts, err := txeh.NewHostsDefault()
144229 if err != nil {
145230 panic(err)
146231 }
147232
148- hosts.AddHost("127.100.100.100", "test")
149- hosts.AddHost("127.100.100.101", "logstash")
150- hosts.AddHosts("127.100.100.102", []string{"a", "b", "c"})
233+ // Add hosts (without comments)
234+ hosts.AddHost("127.100.100.100", "myapp")
235+ hosts.AddHost("127.100.100.101", "database")
236+ hosts.AddHosts("127.100.100.102", []string{"cache", "queue", "search"})
151237
152- hosts.RemoveHosts([]string{"example", "example.machine", "example.machine.example.com"})
153- hosts.RemoveHosts(strings.Fields("example2 example.machine2 example.machine.example.com2"))
238+ // Add hosts with comments (for tracking/organization)
239+ hosts.AddHostWithComment("127.100.100.200", "api.local", "development services")
240+ hosts.AddHostsWithComment("127.100.100.201", []string{"web.local", "admin.local"}, "frontend apps")
154241
242+ // Query existing entries
243+ addresses := hosts.ListAddressesByHost("myapp", true)
244+ fmt.Printf("myapp resolves to: %v\n", addresses)
155245
156- hosts.RemoveAddress("127.1.27.1")
246+ hostnames := hosts.ListHostsByIP("127.100.100.102")
247+ fmt.Printf("Hosts at 127.100.100.102: %v\n", hostnames)
157248
158- removeList := []string{
159- "127.1.27.15",
160- "127.1.27.14",
161- "127.1.27.13",
162- }
249+ // List all hosts with a specific comment
250+ devHosts := hosts.ListHostsByComment("development services")
251+ fmt.Printf("Dev service hosts: %v\n", devHosts)
163252
164- hosts.RemoveAddresses(removeList)
253+ // Remove entries
254+ hosts.RemoveHost("database")
255+ hosts.RemoveHosts([]string{"cache", "queue"})
256+ hosts.RemoveAddress("127.1.27.1")
257+ hosts.RemoveAddresses([]string{"127.1.27.15", "127.1.27.14"})
165258
166- hfData := hosts.RenderHostsFile()
259+ // Remove all entries with specific comments
260+ hosts.RemoveByComment("frontend apps")
261+ hosts.RemoveByComments([]string{"old environment", "deprecated"})
167262
168- // if you like to see what the outcome will
169- // look like
170- fmt.Println(hfData)
263+ // RemoveCIDRs returns an error (CIDR parsing can fail)
264+ if err := hosts.RemoveCIDRs([]string{"10.0.0.0/8"}); err != nil {
265+ panic(err)
266+ }
171267
172- hosts.Save()
173- // or hosts.SaveAs("./test.hosts")
174- }
268+ // Preview changes
269+ fmt.Println(hosts.RenderHostsFile())
175270
271+ // Save changes
272+ err = hosts.Save()
273+ if err != nil {
274+ panic(err)
275+ }
276+ // Or save to a specific file: hosts.SaveAs("./custom.hosts")
277+ }
176278```
177279
178280## Build Release
0 commit comments