Skip to content

Commit a8eff8b

Browse files
committed
chore: Import AI agent instruction files 0.3.0
Signed-off-by: 林博仁(Buo-ren Lin) <buo.ren.lin@gmail.com>
1 parent 5cedd7d commit a8eff8b

File tree

3 files changed

+224
-1
lines changed

3 files changed

+224
-1
lines changed

AGENTS.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# AI agent instruction file
2+
3+
This file contains instructions and guidelines for AI agents interacting with this repository. It outlines the expected behavior, coding standards, and collaboration protocols to ensure effective and efficient contributions.
4+
5+
## Bash coding style
6+
7+
The following coding style guidelines should be followed when writing Bash scripts:
8+
9+
### Shebang
10+
11+
Use `#!/usr/bin/env bash` as the shebang line for portability across different environments.
12+
13+
### Parameter naming
14+
15+
* Use lowercase letters and underscores for variable names (e.g., `my_variable`) to enhance readability.
16+
* Only use uppercase letters for variables whose values are sourced from the environment.
17+
18+
### Parameter expansion
19+
20+
Use `${var}` instead of `$var` for variable references to improve readability and avoid ambiguity.
21+
22+
This also applies to positional parameters, e.g., use `${1}` instead of `$1`.
23+
24+
### Message reporting
25+
26+
* If the program's output is intended to be used as input for other programs, avoid implementing non-error messages at all.
27+
* Use `printf` instead of `echo` for formatted output.
28+
* Prepend log level tags in the following format(except for help text):
29+
+ `Info:`
30+
+ `Warning:`
31+
+ `Error:`
32+
+ `FATAL:`
33+
+ `DEBUG:`
34+
35+
### Linting
36+
37+
Use ShellCheck for linting.
38+
39+
### Defensive interpreter behavior
40+
41+
The following shell options should be set at the beginning of each script to ensure robust error handling:
42+
43+
```bash
44+
set -o errexit # Exit on most errors (see the manual)
45+
set -o nounset # Disallow expansion of unset variables
46+
```
47+
48+
Do not set `pipefail`.
49+
50+
If the script contains functions, also include:
51+
52+
```bash
53+
set -o errtrace # Ensure the error trap is inherited
54+
```
55+
56+
### Conditional constructs
57+
58+
* When using `if...else` constructs, always check the incorrect condition first. For example:
59+
60+
```bash
61+
if ! is_port_valid "${user_input}"; then
62+
printf \
63+
'Error: Invalid port number, please try again.\n' \
64+
1>&2
65+
return 1
66+
else
67+
# Do something when the condition is expected
68+
fi
69+
```
70+
71+
* Use the `test` shell built-in for conditional expressions. For example, use `if test -f "file"` instead of `if [[ -f "file" ]]`.
72+
73+
The only exception is when using regex matching, which requires `[[ ... ]]`. When doing so always define a regex_pattern variable instead of embedding the regex directly in the conditional expression.
74+
75+
### Pattern matching
76+
77+
* Use the `[[ ... ]]` construct for validating user inputs when applicable.
78+
79+
Store the regex pattern in a `regex_` prefix variable instead of embedding it in the conditional expression. For example:
80+
81+
```bash
82+
local regex_digits='^[[:digit:]]+$'
83+
if [[ "${user_input}" =~ ${regex_digits} ]]; then
84+
# Do something when the input is a number
85+
fi
86+
```
87+
88+
### Passing data to subprocesses
89+
90+
* Using the Here Strings syntax (`<<<`) is preferred when passing small amounts of data to subprocesses. For example:
91+
92+
```bash
93+
grep 'pattern' <<< "${data_variable}"
94+
```
95+
96+
### Functions
97+
98+
* Use `function_name(){ ... }` syntax for defining functions. Do not use the `function` keyword.
99+
* Always use `local` for function-local variables.
100+
* Do not use global variables inside functions. Instead, pass them as arguments.
101+
* Use the following pattern to retrieve function arguments:
102+
103+
```bash
104+
local var="${1}"; shift
105+
```
106+
107+
Always use `${1}` parameter expansion and append `shift` command even when the function only has one parameter. This allows cleaner diffs when adding or removing arguments.
108+
109+
* Validate input parameters at the beginning of functions
110+
* Always use `return` to return an exit status from functions. Only use the `exit` builtin in the `init`/`main` function as it is the main logic of the script.
111+
* Place all non `init`/`main` functions _after_ the `init`/`main` function in the script. This allows script readers to access the main script logic easily.
112+
* Use imperative tense for function names.
113+
114+
### Error Handling
115+
116+
* Always check the exit status of commands and handle errors appropriately, don't rely solely on the ERR trap.
117+
* Do not use AND/OR lists syntax.
118+
119+
### Script template
120+
121+
The following script should be used for script creation, rewrites, and style references:
122+
123+
```bash
124+
#!/usr/bin/env bash
125+
# _script_description_
126+
#
127+
# Copyright _copyright_effective_year_ _copyright_holder_name_ <_copyright_holder_contact_>
128+
# SPDX-License-Identifier: CC-BY-SA-4.0
129+
130+
init(){
131+
printf \
132+
'Info: Operation completed without errors.\n'
133+
exit 0
134+
}
135+
136+
printf \
137+
'Info: Configuring the defensive interpreter behaviors...\n'
138+
set_opts=(
139+
# Terminate script execution when an unhandled error occurs
140+
-o errexit
141+
-o errtrace
142+
143+
# Terminate script execution when an unset parameter variable is
144+
# referenced
145+
-o nounset
146+
)
147+
if ! set "${set_opts[@]}"; then
148+
printf \
149+
'Error: Unable to configure the defensive interpreter behaviors.\n' \
150+
1>&2
151+
exit 1
152+
fi
153+
154+
printf \
155+
'Info: Checking the existence of the required commands...\n'
156+
required_commands=(
157+
realpath
158+
)
159+
flag_required_command_check_failed=false
160+
for command in "${required_commands[@]}"; do
161+
if ! command -v "${command}" >/dev/null; then
162+
flag_required_command_check_failed=true
163+
printf \
164+
'Error: This program requires the "%s" command to be available in your command search PATHs.\n' \
165+
"${command}" \
166+
1>&2
167+
fi
168+
done
169+
if test "${flag_required_command_check_failed}" == true; then
170+
printf \
171+
'Error: Required command check failed, please check your installation.\n' \
172+
1>&2
173+
exit 1
174+
fi
175+
176+
printf \
177+
'Info: Configuring the convenience variables...\n'
178+
if test -v BASH_SOURCE; then
179+
# Convenience variables may not need to be referenced
180+
# shellcheck disable=SC2034
181+
{
182+
printf \
183+
'Info: Determining the absolute path of the program...\n'
184+
if ! script="$(
185+
realpath \
186+
--strip \
187+
"${BASH_SOURCE[0]}"
188+
)"; then
189+
printf \
190+
'Error: Unable to determine the absolute path of the program.\n' \
191+
1>&2
192+
exit 1
193+
fi
194+
script_dir="${script%/*}"
195+
script_filename="${script##*/}"
196+
script_name="${script_filename%%.*}"
197+
}
198+
fi
199+
# Convenience variables may not need to be referenced
200+
# shellcheck disable=SC2034
201+
{
202+
script_basecommand="${0}"
203+
script_args=("${@}")
204+
}
205+
206+
printf \
207+
'Info: Setting the ERR trap...\n'
208+
trap_err(){
209+
printf \
210+
'Error: The program has encountered an unhandled error and is prematurely aborted.\n' \
211+
1>&2
212+
}
213+
if ! trap trap_err ERR; then
214+
printf \
215+
'Error: Unable to set the ERR trap.\n' \
216+
1>&2
217+
exit 1
218+
fi
219+
220+
init
221+
```

GEMINI.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

REUSE.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ version = 1
1313
[[annotations]]
1414
path = [
1515
"*.README.md",
16-
"**/README.md"
16+
"**/README.md",
17+
"AGENTS.md"
1718
]
1819
SPDX-FileCopyrightText = '2025 林博仁(Buo-ren Lin) <buo.ren.lin@gmail.com>'
1920
SPDX-License-Identifier = 'CC-BY-SA-4.0+'

0 commit comments

Comments
 (0)