From 2f441319e48df0636e2eb8628a79cab2e53ea809 Mon Sep 17 00:00:00 2001 From: gold-silver-copper <157451540+gold-silver-copper@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:34:53 -0700 Subject: [PATCH 1/4] fix: pass the command to loop_lib as argv Implements [[tasks/harmony-2756]] --- src/main.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1670f1d..8f70bb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Result; use clap::{CommandFactory, Parser}; use colored::*; -use loop_lib::{expand_directories, parse_config, run, LoopConfig}; +use loop_lib::{display_command, expand_directories, parse_config, run, LoopConfig}; use std::path::PathBuf; #[derive(Parser)] @@ -50,15 +50,13 @@ fn main() -> Result<()> { std::process::exit(0); } - let command = cli.command.join(" "); - // Parse the .meta file let absolute_path = std::env::current_dir()?.join(&config_path); if cli.verbose { println!("{}", "Verbose mode enabled".green()); println!("\nResolved config file path: {}", absolute_path.display()); - println!("Executing command: {command}"); + println!("Executing command: {}", display_command(&cli.command)); } let mut config = if config_path.exists() { @@ -85,7 +83,7 @@ fn main() -> Result<()> { config.directories = dirs; } - run(&config, &command)?; + run(&config, &cli.command)?; Ok(()) } From 1e40e2fd948951f3241aac78f1a649b08fdd9dea Mon Sep 17 00:00:00 2001 From: t Date: Sun, 25 Oct 2026 05:00:19 -0700 Subject: [PATCH 2/4] ci: build against dependency branches of the same name Clones loop_lib (and the other deps) from this PR's branch when it exists, like meta_cli and meta_git_cli do, so cross-repo changes test together. Implements [[tasks/harmony-2756]] --- .github/workflows/ci.yml | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ee93a0..34633b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,8 +27,19 @@ jobs: - name: Clone dependencies shell: bash + env: + BRANCH: ${{ github.head_ref || github.ref_name }} run: | - git clone --depth 1 https://github.com/gitkb/loop_lib.git + for repo in loop_lib; do + if git clone --depth 1 -b "$BRANCH" "https://github.com/gitkb/${repo}.git" 2>/dev/null; then + echo "Cloned ${repo}@${BRANCH}" + elif git clone --depth 1 "https://github.com/gitkb/${repo}.git"; then + echo "Branch ${BRANCH} not found for ${repo}; falling back to default branch" + else + echo "::error::Failed to clone ${repo}" + exit 1 + fi + done - name: Create workspace Cargo.toml shell: bash @@ -67,8 +78,19 @@ jobs: path: loop_cli - name: Clone dependencies + env: + BRANCH: ${{ github.head_ref || github.ref_name }} run: | - git clone --depth 1 https://github.com/gitkb/loop_lib.git + for repo in loop_lib; do + if git clone --depth 1 -b "$BRANCH" "https://github.com/gitkb/${repo}.git" 2>/dev/null; then + echo "Cloned ${repo}@${BRANCH}" + elif git clone --depth 1 "https://github.com/gitkb/${repo}.git"; then + echo "Branch ${BRANCH} not found for ${repo}; falling back to default branch" + else + echo "::error::Failed to clone ${repo}" + exit 1 + fi + done - name: Create workspace Cargo.toml run: | @@ -108,8 +130,19 @@ jobs: path: loop_cli - name: Clone dependencies + env: + BRANCH: ${{ github.head_ref || github.ref_name }} run: | - git clone --depth 1 https://github.com/gitkb/loop_lib.git + for repo in loop_lib; do + if git clone --depth 1 -b "$BRANCH" "https://github.com/gitkb/${repo}.git" 2>/dev/null; then + echo "Cloned ${repo}@${BRANCH}" + elif git clone --depth 1 "https://github.com/gitkb/${repo}.git"; then + echo "Branch ${BRANCH} not found for ${repo}; falling back to default branch" + else + echo "::error::Failed to clone ${repo}" + exit 1 + fi + done - name: Create workspace Cargo.toml run: | From 13f3035ec509ac8d4cf85bbde0ea3fa00aaafe2c Mon Sep 17 00:00:00 2001 From: t Date: Sun, 25 Oct 2026 06:47:52 -0700 Subject: [PATCH 3/4] docs: library example passes the config and an argv Implements [[tasks/harmony-2756]] --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 510f385..984c510 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,8 @@ let config = LoopConfig { ..Default::default() }; -let results = run(&["npm", "test"], &config)?; +// The program and its arguments, run as given (no shell) +run(&config, &["npm".to_string(), "test".to_string()])?; ``` See [loop_lib documentation](../loop_lib/) for details. From b7e4eb4ad6e1286596285564ffd0d4ce6e3a4166 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 25 Oct 2026 15:32:32 -0700 Subject: [PATCH 4/4] docs: aliases are split into words, not run by a shell Implements [[tasks/harmony-2756]] --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 984c510..3704e80 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,15 @@ Add aliases to your global config: loop --add-aliases-to-global-looprc ``` +loop runs commands without a shell, so an alias value is split into words +(POSIX quoting, nothing expanded or run) that replace the program. An alias +`ll="ls -la | less"` therefore runs `ls` with the arguments `-la`, `|` and +`less`. For pipes and `&&`, ask for a shell: + +```bash +loop sh -c 'ls -la | less' +``` + ### Combining with Other Tools ```bash