diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/specs/2026-10-19-clone-tool-design.md | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-19-clone-tool-design.md b/docs/superpowers/specs/2026-10-19-clone-tool-design.md new file mode 100644 index 0000000..09d3be5 --- /dev/null +++ b/docs/superpowers/specs/2026-10-19-clone-tool-design.md @@ -0,0 +1,78 @@ +# Clone tool: design + +Date: 2026-10-19. Status: implemented (2026-10-19). + +## Goal + +Ask the assistant to clone a public repository ("clone this repo: +https://github.com/owner/repo") and have it land in the right folder of +`~/Programming/GIT`: `GITHUB/`, `GITLAB/`, `FORGE/`, or a folder already +approved for that host. Public repositories only, plain `git clone`, no +SSH aliases or keys. + +The assistant must not decide two things alone: a host with no folder yet, +and a repository that is already cloned. Both are asked, with a concrete +action, never a bare "skip". + +## Tool + +`examples/tools/clone.toml`, installed to +`~/.config/desktop-assistant/tools/` like the others. No change to +`assistant.py`. + +```toml +command = ["clone.sh", "{url}", "{to}", "{update}"] +timeout = 300 +``` + +- `url`: the repository URL. +- `to`: only when the user approved a new host folder; the folder name. +- `update`: `1` to pull an existing clone. + +`examples/tools/clone.sh`: + +- Parses `https://host/owner/repo` and `git@host:owner/repo` alike; `repo` + is the last path segment with a trailing `/` and a `.git` suffix removed. + Both `host` and `repo` are validated as plain names, so neither can + escape the tree. +- Resolves `host -> folder` from the mapping file. Absent, it is seeded + with `github.com -> GITHUB`, `gitlab.com -> GITLAB`, + `forge.slackware.nl -> FORGE`. +- Target is `<root>/<folder>/<repo>` (`CLONE_ROOT`, default + `~/Programming/GIT`). +- Known host, target free: `git clone` and report it. No question. +- Unknown host: prints the folder to offer (hostname without its last + label, uppercased: `codeberg.org -> CODEBERG`) and does nothing. +- Target exists: prints "already cloned" and does nothing. With + `update=1`, runs `git pull --ff-only` and reports the result; a diverged + clone is an error, not a merge. +- A `to` given for an unknown host clones there and appends + `host<TAB>folder` to the mapping, so that host is known from then on. + An existing mapping is never duplicated or overwritten. + +## Mapping file + +`~/.config/desktop-assistant/clone-hosts` (`CLONE_MAP`), one +`host<TAB>folder` line per host, user-editable. It lives outside the tool +directory so reinstalling the tools does not lose it, and the file is the +single source of truth: nothing is hardcoded in the script beyond the +seed. + +## Check + +`test-clone.sh`: a scratch `CLONE_ROOT` and `CLONE_MAP`, and a `git` stub +on `PATH` that records its argv and creates the target, so no network and +no real tree. Covers seeding, clone argv, trailing slash and `.git`, the +unknown-host message, the approved folder being remembered and used on +the next clone without a question, no duplicate map line, the +already-cloned message, the update argv, and the refused inputs. + +Live, against the running model: ask for a known host and an unknown host, +accept the offered folder, ask for the same host again (must ask nothing), +then ask for an existing repo (must offer an update, never a second +clone). + +## Not included + +Private repositories (no credentials), clone depth or branches, and +opening the clone in an editor or agent after it lands. |
