๐ค Agent Instructions
August 27, 2025 ยท View on GitHub
This file contains instructions for AI agents on how to interact with and contribute to this repository.
๐ General Agent Guidance
This section outlines the universal rules and expectations for any AI agent working within this repository.
-
Safety and Quality First: The highest priority is to produce secure, well-documented, and high-quality code. Do not introduce vulnerabilities, hardcoded secrets, or unreadable code.
-
Propose a Plan: For any new task, first provide a brief plan of action. This plan should clearly outline the intended changes and the rationale behind them.
-
Maintain Context: Before making any changes, an agent must read and understand the relevant files, including the project's main documentation and existing code structure.
-
Clear Contributions: All contributions must be submitted via a pull request with a clear, concise commit message and a brief description of the changes.
๐ Project-Specific Guidelines
Tone and Style
- Art Gallery with Humor: The overall tone of the project, especially in user-facing documentation like READMEs, should be that of a slightly quirky art gallery curator. Think "art gallery with a bit of humor".
Bash Compatibility
- Bash v3.2 is the target: The main
screensaver.shscript must be compatible with Bash v3.2. This is to ensure it runs on a wide variety of systems, including older macOS versions. - Individual screensavers: Individual screensavers can use newer bash features, but it's good practice to stick to v3.2 if possible.
- Cross-platform: All scripts should be written to be cross-platform, working on macOS, Linux, WSL, Cygwin, etc. Avoid using platform-specific commands without fallbacks.
Bash Scripting Style
The following scripting guidelines are heavily based on the Bash Style Guide by Dave Eddy, which should be considered the primary reference for style. Adhere to the following principles to ensure scripts are safe, predictable, and maintainable.
- Shebang: Start scripts with
#!/usr/bin/env bashfor portability. - Error Checking: Always check for potential errors, especially for commands that can fail, like
cd.# wrong cd /some/path rm file # right cd /some/path || exit 1 rm file set -e: Do not useset -e. Handle errors explicitly. It can have unintended consequences.- Quoting: This is critical.
- Use double quotes (
") for strings that require variable expansion. - Use single quotes (
') for all other literal strings. - Always quote variable expansions (
"$var") to prevent word-splitting and globbing issues.
- Use double quotes (
- Variables:
- Use lowercase variable names (e.g.,
my_var). - Use
localfor all variables inside functions.
- Use lowercase variable names (e.g.,
- Functions:
- Do not use the
functionkeyword. - Use
my_func() { ... }syntax.
- Do not use the
- Conditionals:
- Always use
[[ ... ]]for conditional testing, not[ ... ]ortest. - Use
((...))for arithmetic comparisons (e.g.,((a > b))).
- Always use
- Command Substitution:
- Always use
$(...)for command substitution, not backticks.
- Always use
- Arrays:
- Use Bash arrays to manage lists of items instead of space-separated strings.
- Iterate over arrays using
for item in "${my_array[@]}"; do ... done.
- Avoid External Commands:
- Use Bash's built-in parameter expansion for string manipulation (e.g.,
${var/foo/bar}). - Use globbing (
*) to iterate over files, notls. - Avoid
catwhen a command can read a file directly (e.g.,grep "pattern" file).
- Use Bash's built-in parameter expansion for string manipulation (e.g.,
eval: Never useeval.
Screen Handling
tputis your friend: Usetputfor all screen manipulations, such as moving the cursor, changing colors, and clearing the screen. This ensures that the scripts are portable across different terminal types.- Colors: Use
tput setaf(foreground) andtput setab(background) for colors. The standard 8-color palette is the most portable. - Animations: Animations are created by a loop of clearing the screen (or parts of it), drawing the next frame, and then sleeping for a short period.
sleep 0.1is a common choice.
Project Structure
screensaver.sh: The main entry point. It displays a menu of screensavers and runs the chosen one.gallery/: Each subdirectory ingallery/is a screensaver.<name>/<name>.sh: The main script for the screensaver.<name>/config.sh: Metadata for the screensaver (name, tagline, etc.).
spotlight/: Contains helper scripts for generating previews and other marketing materials.jury/: Contains thebatstest suite.
General Tips
- Cleanup is crucial: Always use
trapto ensure that the terminal is restored to a usable state when the user pressesCtrl+C. This includes showing the cursor again (tput cnorm), resetting colors (tput sgr0), and clearing the screen. - Subshells for safety: The main
screensaver.shscript runs each screensaver in a subshell. This is to prevent the screensaver from accidentally exiting the main menu. - Tools: This project uses
asciinemato record terminal sessions as.castfiles andaggto convert those.castfiles into animated GIFs. Thespotlight/smile-for-the-camera.shscript automates this process.
๐งช Testing
The tests for this project are written using the bats (Bash Automated Testing System) framework.
Running Tests
The tests should be run from the root of the repository using the project-specific command, which executes all test files in the jury/ directory:
bats jury
To run a specific test file, you can execute bats jury/my_test.bats.
Test Structure
Tests are located in the jury/ directory. The main test file is jury/tests.bats, which tests the main screensaver.sh script. There are also individual test files for each screensaver.
A BATS test file is a Bash script with special syntax. Here is a typical structure:
#!/usr/bin/env bats
# setup() { ... } # optional: runs before each test
# teardown() { ... } # optional: runs after each test
@test "description of the test" {
# The test code goes here
run my_script "some argument"
[ "$status" -eq 0 ]
[ "$output" = "expected output" ]
}
Key BATS Concepts
-
Key Variables:
run: Executes a command and captures its output and status code.$status: The exit status of the command run.$output: The combined stdout and stderr of the command run.$lines: An array containing each line of the output.
-
Best Practices:
- Isolate Tests: Each
@testshould be independent. Usesetupandteardownfunctions to prepare and clean up the test environment if needed. - Be Specific: Test descriptions should clearly state what is being tested.
- Assert One Thing: Ideally, each test should assert a single condition or outcome.
- Use Helpers: For complex setup or repeated assertions, create helper functions within your test files. BATS automatically exports functions that are not named
setuporteardown.
- Isolate Tests: Each
Project-Specific Considerations
- Dependencies: The tests require
bats,bats-support, andbats-assert. These are not checked in to the repository. Refer to the "Environment Setup Guide" in "Jules's Corner" for instructions on installing them using theassemble-the-jury.shscript. It is better to download the release tarballs and extract them rather than cloning withgit. - Paths: The test scripts are written with the assumption that they are being run from the root of the repository. All paths in the test files should be relative to the root.
timeoutand Assertions: Many of the tests usetimeoutto run the screensavers for a short period. Since the screensavers are designed to run indefinitely,timeoutwill kill them, resulting in a non-zero exit code. Therefore, the tests should useassert_failureto check for this expected failure, notassert_success.- Environment Limitations: The testing environment can be restrictive. Commands like
cd,pwd, andgit restoremay not work as expected. It's important to be aware of these limitations and find workarounds when necessary.
Learnings on Test Execution and Reporting
This section documents the work done to simplify test execution and reporting.
-
Idempotent Dependency Installation:
- Issue: The
assemble-the-jury.shscript would re-download dependencies on every run, which was slow and could fail due to network timeouts. - Resolution: I modified the script to first check if the dependency directories exist before attempting to download and extract them. This makes the script idempotent and much faster on subsequent runs.
- Issue: The
-
Automated Test Runner:
- Issue: Running the tests required two separate commands: one to install dependencies and another to run the
batssuite. The process was manual and didn't save the results. - Resolution: I created a new script,
jury/render-the-verdict.sh, which automates the entire process. It callsassemble-the-jury.shand then runs the test suite twice, saving the output tojury/verdict.txt(human-readable) andjury/verdict.tap(machine-readable).
- Issue: Running the tests required two separate commands: one to install dependencies and another to run the
-
Location-Independent Scripts:
- Issue: The initial version of
render-the-verdict.shrelied on being run from the repository root. - Resolution: I refactored the script to be location-independent. It now uses
dirnameon${BASH_SOURCE[0]}to determine its own location and constructs absolute paths, allowing it to be run from anywhere on the system.
- Issue: The initial version of
-
Fix for Hanging Trap Handler:
- Issue: The test suite was timing out because the
life.shscript had areadcommand in itstrap cleanupfunction, which would hang in a non-interactive environment. This issue was previously noted in thetour-the-gallery.shlearnings but the fix was not applied here. - Resolution: I removed the problematic
readcommand fromgallery/life/life.sh, allowing the script to terminate correctly when sent a signal bytimeout.
- Issue: The test suite was timing out because the
-
Fix for Incorrect Trap Handlers:
- Issue: Some scripts, like
cutesaver.sh, were only trappingSIGINT(Ctrl+C). This meant that when run undertimeout(which sendsSIGTERM), their cleanup functions would not execute, potentially leaving the terminal in a bad state. - Resolution: I updated the
trapcommands in these scripts to also catchEXIT,TERM, andQUIT, ensuring that cleanup always runs.
- Issue: Some scripts, like
-
New Screensaver Template Fix:
- Issue: The template used to create new screensavers (
screensaver.sh --new) contained the same incorrecttraphandler, which would have propagated the bug to all new screensavers. - Resolution: I updated the template in
screensaver.shto use the correct, robusttrapcommand.
- Issue: The template used to create new screensavers (
๐จโ๐ป Jules's Corner
This section contains notes and learnings specific to the agent Jules.
Environment Setup Guide
To prepare the environment for development and testing, follow these steps:
- Install Core Dependencies: The project requires
bc. You can install it using the appropriate package manager (e.g.,apt-get install bcorbrew install bc). - Set up the Test Suite: The BATS test suite has dependencies that are not in the repository. Run the following script to download and install them locally into
jury/test_libs/:./jury/assemble-the-jury.sh - Run the Tests: To verify the setup, run the full test suite using the automated runner script. The results will be saved in
jury/verdict.txtandjury/verdict.tap../jury/render-the-verdict.sh - Be Aware of Environment Constraints:
aggInstallation: Theaggtool for GIF generation is difficult to install. Refer to the "Learnings onaggInstallation" section for details on what has been tried.asciinemaVersion: The installed version ofasciinemadoes not support thecutsubcommand.- Filesystem Persistence: When running a series of commands that depend on each other (like downloading and then extracting a file), chain them together in a single
run_in_bash_sessioncall with&&to avoid issues with filesystem persistence between tool calls.
Learnings on tour-the-gallery.sh
This document summarizes the issues I encountered and the solutions I implemented while debugging the spotlight/tour-the-gallery.sh script.
Key Issues and Resolutions
-
Non-Standard Timeout Function:
- Issue: The script initially used a custom
run_with_timeoutfunction which was not accessible within the subshell created byasciinema rec, causing recording failures. - Resolution: I replaced the custom function with the standard Linux
timeoutcommand for better portability and reliability.
- Issue: The script initially used a custom
-
Hidden Dependency (
bc):- Issue: The
speaky.shscreensaver failed because it depends on thebccommand-line calculator, which was not installed in the environment. - Resolution: I identified and installed the
bcpackage to satisfy the dependency.
- Issue: The
-
Unsupported
asciinemaSubcommand:- Issue: The script used the
asciinema cutsubcommand, which is not available in the version ofasciinemapresent in the execution environment. - Resolution: I refactored the recording logic. Instead of recording a long 10-second clip and cutting a 3-second snippet, the script now directly records a 3-second snippet after a 3-second pause (
sleep 3; timeout 3s ...), eliminating the need for thecutcommand.
- Issue: The script used the
-
Interactive Scripts in Non-Interactive Environment:
- Issue: Several screensavers (e.g.,
cutesaver.sh,life.sh) used interactivereadcommands to pause between frames or wait for user input. This caused the main script to hang indefinitely. - Resolution: I replaced the interactive
readcommands in the affected screensavers with non-interactivesleepcommands.
- Issue: Several screensavers (e.g.,
Unresolved Issues & Final State
- Persistent Timeouts: Despite the fixes above, the
tour-the-gallery.shscript continues to time out during the final step of converting the concatenated.castfile into a.gifusing theaggcommand. - Hypothesis: The timeout is likely caused by one of two things:
- The
aggcommand is extremely slow when processing the large, concatenatedoverview.castfile. - One of the screensavers is still producing a subtly malformed
.castfile that isn't caught by the validation logic, causingaggto hang or fail silently (by creating an empty GIF).
- The
Learnings on agg Installation
The spotlight/smile-for-the-camera.sh script requires the agg tool to generate GIFs. During my work on this project, I encountered significant difficulties installing agg in the provided environment. This section documents the issues for future reference.
pip install agg: Thepippackage foraggdoes not seem to install an executable, but rather a library. This means thatcommand -v aggwill fail even after a successfulpipinstallation.- Pre-built Binaries: The official documentation for
aggrecommends downloading a pre-built binary from the GitHub releases page. However, I was unable to find a direct download link for the correct architecture (x86_64-unknown-linux-gnu) on the releases page. My attempts to guess the URL resulted in 404 errors. x-cmd: I found a third-party tool calledx-cmdthat simplifies the installation of command-line tools. However,x-cmditself is not installed in this environment, so I was unable to use it.
Due to these issues, I was unable to get a working version of agg installed. The tasks related to fixing the GIF generation for the pipes and life screensavers have been postponed until this issue can be resolved.
Learnings on the Bats Test Environment
This section documents the issues encountered while attempting to fix the bats test suite in the jury/ directory.
Key Issues and Resolutions
-
Dependency Management:
- Issue: The
batstest dependencies (bats-core,bats-support,bats-assert) are not checked into the repository. - Resolution: I created a setup script at
jury/assemble-the-jury.shto automate the download and extraction of these dependencies into ajury/test_libs/directory. I also added this directory to the.gitignorefile.
- Issue: The
-
Filesystem Persistence in the Environment:
- Issue: The execution environment appears to have issues with filesystem persistence between separate
run_in_bash_sessiontool calls. Changes made in one call (like downloading a file) were not always present in the next call, leading to "No such file or directory" errors. - Workaround: To get a consistent result, I had to chain all commands (dependency download, extraction, and test execution) into a single, long
run_in_bash_sessioncommand using&&.
- Issue: The execution environment appears to have issues with filesystem persistence between separate
Unresolved Issues & Final State
- Path Loading in Bats: The primary blocker is an issue with how
batsloads dependency files. The test scripts use relative paths (e.g.,load 'libs/bats-support/load'). My attempts to correct these paths to point to the newjury/test_libsdirectory were unsuccessful. - Hypothesis: The
batsexecutable, when run from the repository root, seems to have an unexpected behavior in this environment when resolving the relativeloadpaths from within the test files. For example, my attempts to change the path tojury/test_libs/bats-support/loadresulted inbatslooking for/app/jury/jury/test_libs/..., indicating a misinterpretation of the path. All attempts to modify the files programmatically resulted in corrupted paths. - Final State: The test environment setup is now automated via
jury/assemble-the-jury.sh. However, the tests themselves are still not runnable due to the path loading issue. The.batsfiles have been restored to their original, incorrect state. A future developer should focus on fixing theloadpaths within the.batsfiles, perhaps by experimenting with different relative paths (../test_libs) or otherbatsloading mechanisms.
๐ External Resources
Here are some helpful resources for Bash scripting and BATS testing:
- Bash Style Guide: style.ysap.sh
- BATS Documentation: BATS on GitHub
- Bash Reference: BashGuide