detached f57d176

Allow zotfiles from any GitHub owner

commit
f57d176db0afb48edb77178b1a3894ad87fe418f
author
patriceckhart · · 2026-08-03 17:26 UTC
parent
6bae491
signature
unsigned
4 files · +39 -40
M README.md +3 -3
@@ -249,11 +249,11 @@ A zotfile packages an agent's instructions, skills, requirements, and enforced t
249249 ```bash
250250 zot run ./my-agent
251251 zot run ./my-agent.zot
252-zot run zot-maintenance --cwd /path/to/zot
253-zot run https://github.com/patriceckhart/agents/zot-maintenance --cwd /path/to/zot
252+zot run frkr/zot-archify
253+zot run acme/agents/code-reviewer --cwd /path/to/project
254254 ```
255255
256-Short names resolve local-first: zot checks the matching directory and `.zot` archive before falling back to the official GitHub agent collection. For GitHub sources, zot downloads the repository archive into a temporary directory, validates and runs the selected agent, then removes the downloaded source when the command exits. Agent data, consent receipts, and sessions still persist under `$ZOT_HOME`. See [docs/zotfiles.md](docs/zotfiles.md) for authoring, permissions, packaging, and current limitations.
256+Single-part names resolve only to a matching local directory or `.zot` archive. Anyone can publish an agent as a public GitHub repository and run it as `owner/repository`, or publish a collection and run an agent directory as `owner/repository/agent`. zot has no built-in owner, official collection, configured registry, or allowlist. For GitHub sources, zot downloads the repository archive into a temporary directory, validates and runs the selected agent, then removes the downloaded source when the command exits. Agent data, consent receipts, and sessions still persist under `$ZOT_HOME`. See [docs/zotfiles.md](docs/zotfiles.md) for authoring, permissions, packaging, and current limitations.
257257
258258 ## Embedding
259259
@@ -249,11 +249,11 @@ A zotfile packages an agent's instructions, skills, requirements, and enforced t
249 ```bash249 ```bash
250 zot run ./my-agent250 zot run ./my-agent
251 zot run ./my-agent.zot251 zot run ./my-agent.zot
252-zot run zot-maintenance --cwd /path/to/zot252+zot run frkr/zot-archify
253-zot run https://github.com/patriceckhart/agents/zot-maintenance --cwd /path/to/zot253+zot run acme/agents/code-reviewer --cwd /path/to/project
254 ```254 ```
255 255
256-Short names resolve local-first: zot checks the matching directory and `.zot` archive before falling back to the official GitHub agent collection. For GitHub sources, zot downloads the repository archive into a temporary directory, validates and runs the selected agent, then removes the downloaded source when the command exits. Agent data, consent receipts, and sessions still persist under `$ZOT_HOME`. See [docs/zotfiles.md](docs/zotfiles.md) for authoring, permissions, packaging, and current limitations.256+Single-part names resolve only to a matching local directory or `.zot` archive. Anyone can publish an agent as a public GitHub repository and run it as `owner/repository`, or publish a collection and run an agent directory as `owner/repository/agent`. zot has no built-in owner, official collection, configured registry, or allowlist. For GitHub sources, zot downloads the repository archive into a temporary directory, validates and runs the selected agent, then removes the downloaded source when the command exits. Agent data, consent receipts, and sessions still persist under `$ZOT_HOME`. See [docs/zotfiles.md](docs/zotfiles.md) for authoring, permissions, packaging, and current limitations.
257 257
258 ## Embedding258 ## Embedding
259 259
M docs/zotfiles.md +15 -17
@@ -2,7 +2,7 @@
22
33 A zotfile packages an agent's behavior into one portable `.zot` file. It can contain the agent's instructions, reusable skills, static assets, and metadata describing the runtime, model, operating-system, binary, and tool permissions it needs.
44
5-The current implementation supports creating, inspecting, verifying, and running local directories and `.zot` archives. It can also run an agent directory directly from a public GitHub repository without keeping a clone. Short names resolve local-first and then fall back to zot's official GitHub agent collection. Indexed registry distribution, installation, signatures, bundled executable extensions, network permissions, and environment permissions are not implemented yet.
5+The current implementation supports creating, inspecting, verifying, and running local directories and `.zot` archives. It can also run an agent repository or directory directly from any public GitHub repository without keeping a clone. zot has no built-in owner or official collection. Indexed registry distribution, installation, signatures, bundled executable extensions, network permissions, and environment permissions are not implemented yet.
66
77 ## Quick start
88
@@ -513,44 +513,42 @@ zot run ./my-agent.zot --json "Do the task"
513513
514514 Arguments after the reference use zot's normal CLI parser, so model, provider, reasoning, cwd, session, tool, and output-mode flags remain available. The manifest still imposes its permission and compatibility ceiling. In interactive mode, enabling **show loaded resources at startup** in `/settings` displays the manifest name in an `[Agent]` section above the transcript.
515515
516-Local filesystem directories, local archive paths, short names, and public GitHub agent-directory URLs are accepted. A short name uses local-first resolution:
516+Local filesystem directories, local archive paths, GitHub shorthand, and public GitHub agent-directory URLs are accepted. A single-part name resolves only to a matching local directory or `.zot` archive:
517517
518518 ```bash
519-zot run zot-maintenance
519+zot run my-agent
520520 ```
521521
522-Zot checks `./zot-maintenance` and `./zot-maintenance.zot` before falling back to `https://github.com/patriceckhart/agents/zot-maintenance`. This makes local development override the remote collection without an install or cache step.
523-
524-A two-part name is treated as a GitHub `owner/repo` reference. Resolution is local-first, then the repository root:
522+A two-part name is treated as a GitHub `owner/repository` reference. Resolution remains local-first, then uses the repository root:
525523
526524 ```bash
527525 zot run frkr/zot-archify
528526 ```
529527
530-The legacy `agents/<name>` form remains reserved for selecting an agent directory from the official `patriceckhart/agents` collection:
528+Use three or more parts to select an agent directory from any public GitHub collection:
531529
532530 ```bash
533-zot run agents/zot-maintenance
534-zot run agents\zot-maintenance # also accepted on Windows
531+zot run acme/agents/reviewer
532+zot run acme/clankers/reviewers/go
535533 ```
536534
537-Both parts must use lowercase letters, digits, dots, hyphens, or underscores. Prefix a reference with `./`, use an absolute path, retain the `.zot` suffix, or provide a complete GitHub URL when remote fallback is not wanted.
535+There is no built-in owner, official collection, collection configuration, or allowlist. Every shorthand part must use lowercase letters, digits, dots, hyphens, or underscores. Backslashes are also accepted as separators on Windows. Prefix a reference with `./`, use an absolute path, retain the `.zot` suffix, or provide a complete GitHub URL to force local or explicit remote resolution.
538536
539537 For GitHub, zot downloads the repository archive into a temporary directory, selects the requested agent subdirectory, validates it, runs it, and removes the downloaded files when the command exits:
540538
541539 ```bash
542-zot run https://github.com/patriceckhart/agents/zot-maintenance --cwd /path/to/zot
540+zot run https://github.com/acme/agents/reviewer
543541 ```
544542
545-Both the legacy official-collection form above and a standard GitHub tree URL are supported:
543+A standard GitHub tree URL is also supported:
546544
547545 ```bash
548-zot run https://github.com/patriceckhart/agents/tree/main/zot-maintenance
546+zot run https://github.com/acme/agents/tree/main/reviewer
549547 ```
550548
551549 Short forms read the repository's default branch through GitHub's `HEAD` archive. A tree URL uses the branch or tag in the URL. Private repositories and branch or tag names containing `/` are not currently supported. The downloaded source is temporary, but normal agent data, consent receipts, and session transcripts remain under `$ZOT_HOME`.
552550
553-Short-name and `owner/repo` fallbacks are direct GitHub mappings, not an indexed or signed registry. Installed names, arbitrary URLs, OCI references, and third-party registry configuration are not resolved yet.
551+`owner/repository` and `owner/repository/path` are direct GitHub mappings, not an indexed or signed registry. Installed names, arbitrary URLs, and OCI references are not resolved yet.
554552
555553 ### `zot pack`
556554
@@ -575,7 +573,7 @@ Packing validates the manifest and directory, then creates a zstd-compressed tar
575573 ```bash
576574 zot inspect ./my-agent
577575 zot inspect ./my-agent.zot
578-zot inspect https://github.com/patriceckhart/agents/zot-maintenance
576+zot inspect https://github.com/acme/agents/code-reviewer
579577 ```
580578
581579 Inspection validates and prints the agent's name, version, description, digest, declared permissions, and complete file list. It does not execute the agent.
@@ -620,8 +618,8 @@ Archive extraction rejects absolute paths and parent traversal. Unsupported tar
620618 Implemented now:
621619
622620 - local directories and `.zot` archives
623-- local-first short-name resolution to the official GitHub agent collection
624-- local-first `owner/repo` resolution to `https://github.com/owner/repo`
621+- local-only resolution for single-part names
622+- local-first `owner/repository` and `owner/repository/path` resolution to any public GitHub repository
625623 - temporary execution of agent directories from public GitHub repositories
626624 - `zot pack`, `zot inspect`, `zot verify`, and `zot run`
627625 - canonical tar creation with zstd compression
@@ -2,7 +2,7 @@
2 2
3 A zotfile packages an agent's behavior into one portable `.zot` file. It can contain the agent's instructions, reusable skills, static assets, and metadata describing the runtime, model, operating-system, binary, and tool permissions it needs.3 A zotfile packages an agent's behavior into one portable `.zot` file. It can contain the agent's instructions, reusable skills, static assets, and metadata describing the runtime, model, operating-system, binary, and tool permissions it needs.
4 4
5-The current implementation supports creating, inspecting, verifying, and running local directories and `.zot` archives. It can also run an agent directory directly from a public GitHub repository without keeping a clone. Short names resolve local-first and then fall back to zot's official GitHub agent collection. Indexed registry distribution, installation, signatures, bundled executable extensions, network permissions, and environment permissions are not implemented yet.5+The current implementation supports creating, inspecting, verifying, and running local directories and `.zot` archives. It can also run an agent repository or directory directly from any public GitHub repository without keeping a clone. zot has no built-in owner or official collection. Indexed registry distribution, installation, signatures, bundled executable extensions, network permissions, and environment permissions are not implemented yet.
6 6
7 ## Quick start7 ## Quick start
8 8
@@ -513,44 +513,42 @@ zot run ./my-agent.zot --json "Do the task"
513 513
514 Arguments after the reference use zot's normal CLI parser, so model, provider, reasoning, cwd, session, tool, and output-mode flags remain available. The manifest still imposes its permission and compatibility ceiling. In interactive mode, enabling **show loaded resources at startup** in `/settings` displays the manifest name in an `[Agent]` section above the transcript.514 Arguments after the reference use zot's normal CLI parser, so model, provider, reasoning, cwd, session, tool, and output-mode flags remain available. The manifest still imposes its permission and compatibility ceiling. In interactive mode, enabling **show loaded resources at startup** in `/settings` displays the manifest name in an `[Agent]` section above the transcript.
515 515
516-Local filesystem directories, local archive paths, short names, and public GitHub agent-directory URLs are accepted. A short name uses local-first resolution:516+Local filesystem directories, local archive paths, GitHub shorthand, and public GitHub agent-directory URLs are accepted. A single-part name resolves only to a matching local directory or `.zot` archive:
517 517
518 ```bash518 ```bash
519-zot run zot-maintenance519+zot run my-agent
520 ```520 ```
521 521
522-Zot checks `./zot-maintenance` and `./zot-maintenance.zot` before falling back to `https://github.com/patriceckhart/agents/zot-maintenance`. This makes local development override the remote collection without an install or cache step.522+A two-part name is treated as a GitHub `owner/repository` reference. Resolution remains local-first, then uses the repository root:
523-
524-A two-part name is treated as a GitHub `owner/repo` reference. Resolution is local-first, then the repository root:
525 523
526 ```bash524 ```bash
527 zot run frkr/zot-archify525 zot run frkr/zot-archify
528 ```526 ```
529 527
530-The legacy `agents/<name>` form remains reserved for selecting an agent directory from the official `patriceckhart/agents` collection:528+Use three or more parts to select an agent directory from any public GitHub collection:
531 529
532 ```bash530 ```bash
533-zot run agents/zot-maintenance531+zot run acme/agents/reviewer
534-zot run agents\zot-maintenance # also accepted on Windows532+zot run acme/clankers/reviewers/go
535 ```533 ```
536 534
537-Both parts must use lowercase letters, digits, dots, hyphens, or underscores. Prefix a reference with `./`, use an absolute path, retain the `.zot` suffix, or provide a complete GitHub URL when remote fallback is not wanted.535+There is no built-in owner, official collection, collection configuration, or allowlist. Every shorthand part must use lowercase letters, digits, dots, hyphens, or underscores. Backslashes are also accepted as separators on Windows. Prefix a reference with `./`, use an absolute path, retain the `.zot` suffix, or provide a complete GitHub URL to force local or explicit remote resolution.
538 536
539 For GitHub, zot downloads the repository archive into a temporary directory, selects the requested agent subdirectory, validates it, runs it, and removes the downloaded files when the command exits:537 For GitHub, zot downloads the repository archive into a temporary directory, selects the requested agent subdirectory, validates it, runs it, and removes the downloaded files when the command exits:
540 538
541 ```bash539 ```bash
542-zot run https://github.com/patriceckhart/agents/zot-maintenance --cwd /path/to/zot540+zot run https://github.com/acme/agents/reviewer
543 ```541 ```
544 542
545-Both the legacy official-collection form above and a standard GitHub tree URL are supported:543+A standard GitHub tree URL is also supported:
546 544
547 ```bash545 ```bash
548-zot run https://github.com/patriceckhart/agents/tree/main/zot-maintenance546+zot run https://github.com/acme/agents/tree/main/reviewer
549 ```547 ```
550 548
551 Short forms read the repository's default branch through GitHub's `HEAD` archive. A tree URL uses the branch or tag in the URL. Private repositories and branch or tag names containing `/` are not currently supported. The downloaded source is temporary, but normal agent data, consent receipts, and session transcripts remain under `$ZOT_HOME`.549 Short forms read the repository's default branch through GitHub's `HEAD` archive. A tree URL uses the branch or tag in the URL. Private repositories and branch or tag names containing `/` are not currently supported. The downloaded source is temporary, but normal agent data, consent receipts, and session transcripts remain under `$ZOT_HOME`.
552 550
553-Short-name and `owner/repo` fallbacks are direct GitHub mappings, not an indexed or signed registry. Installed names, arbitrary URLs, OCI references, and third-party registry configuration are not resolved yet.551+`owner/repository` and `owner/repository/path` are direct GitHub mappings, not an indexed or signed registry. Installed names, arbitrary URLs, and OCI references are not resolved yet.
554 552
555 ### `zot pack`553 ### `zot pack`
556 554
@@ -575,7 +573,7 @@ Packing validates the manifest and directory, then creates a zstd-compressed tar
575 ```bash573 ```bash
576 zot inspect ./my-agent574 zot inspect ./my-agent
577 zot inspect ./my-agent.zot575 zot inspect ./my-agent.zot
578-zot inspect https://github.com/patriceckhart/agents/zot-maintenance576+zot inspect https://github.com/acme/agents/code-reviewer
579 ```577 ```
580 578
581 Inspection validates and prints the agent's name, version, description, digest, declared permissions, and complete file list. It does not execute the agent.579 Inspection validates and prints the agent's name, version, description, digest, declared permissions, and complete file list. It does not execute the agent.
@@ -620,8 +618,8 @@ Archive extraction rejects absolute paths and parent traversal. Unsupported tar
620 Implemented now:618 Implemented now:
621 619
622 - local directories and `.zot` archives620 - local directories and `.zot` archives
623-- local-first short-name resolution to the official GitHub agent collection621+- local-only resolution for single-part names
624-- local-first `owner/repo` resolution to `https://github.com/owner/repo`622+- local-first `owner/repository` and `owner/repository/path` resolution to any public GitHub repository
625 - temporary execution of agent directories from public GitHub repositories623 - temporary execution of agent directories from public GitHub repositories
626 - `zot pack`, `zot inspect`, `zot verify`, and `zot run`624 - `zot pack`, `zot inspect`, `zot verify`, and `zot run`
627 - canonical tar creation with zstd compression625 - canonical tar creation with zstd compression
M packages/agent/zotfile.go +11 -13
@@ -383,8 +383,6 @@ func loadZotfile(ref string) (zotfileLoaded, func(), error) {
383383 return zotfileLoaded{Dir: tmp, Temp: true, Digest: digest, Manifest: m}, cleanup, nil
384384 }
385385
386-const officialZotfileCollection = "https://github.com/patriceckhart/agents"
387-
388386 func resolveZotfileRef(ref string) (string, error) {
389387 if u, err := url.Parse(ref); err == nil && (u.Scheme == "http" || u.Scheme == "https") {
390388 return ref, nil
@@ -405,23 +403,23 @@ func resolveZotfileRef(ref string) (string, error) {
405403 if strings.HasSuffix(strings.ToLower(ref), ".zot") {
406404 return ref, nil
407405 }
408- collectionRef := strings.ReplaceAll(ref, "\\", "/")
409- parts := strings.Split(collectionRef, "/")
410- if len(parts) == 1 && validZotfileCollectionSegment(parts[0]) {
411- return officialZotfileCollection + "/" + parts[0], nil
406+ githubRef := strings.ReplaceAll(ref, "\\", "/")
407+ parts := strings.Split(githubRef, "/")
408+ if len(parts) == 2 && validGitHubZotfileSegment(parts[0]) && validGitHubZotfileSegment(parts[1]) {
409+ return "https://github.com/" + parts[0] + "/" + parts[1], nil
412410 }
413- if len(parts) == 2 && validZotfileCollectionSegment(parts[0]) && validZotfileCollectionSegment(parts[1]) {
414- // Preserve the original official-collection shorthand, where
415- // agents/<name> selects a subdirectory of patriceckhart/agents.
416- if parts[0] == "agents" {
417- return officialZotfileCollection + "/" + parts[1], nil
411+ if len(parts) >= 3 {
412+ for _, part := range parts {
413+ if !validGitHubZotfileSegment(part) {
414+ return ref, nil
415+ }
418416 }
419- return "https://github.com/" + parts[0] + "/" + parts[1], nil
417+ return "https://github.com/" + strings.Join(parts, "/"), nil
420418 }
421419 return ref, nil
422420 }
423421
424-func validZotfileCollectionSegment(s string) bool {
422+func validGitHubZotfileSegment(s string) bool {
425423 return s != "" && s == strings.ToLower(s) && safeAgentName(s) == s
426424 }
427425
@@ -383,8 +383,6 @@ func loadZotfile(ref string) (zotfileLoaded, func(), error) {
383 return zotfileLoaded{Dir: tmp, Temp: true, Digest: digest, Manifest: m}, cleanup, nil383 return zotfileLoaded{Dir: tmp, Temp: true, Digest: digest, Manifest: m}, cleanup, nil
384 }384 }
385 385
386-const officialZotfileCollection = "https://github.com/patriceckhart/agents"
387-
388 func resolveZotfileRef(ref string) (string, error) {386 func resolveZotfileRef(ref string) (string, error) {
389 if u, err := url.Parse(ref); err == nil && (u.Scheme == "http" || u.Scheme == "https") {387 if u, err := url.Parse(ref); err == nil && (u.Scheme == "http" || u.Scheme == "https") {
390 return ref, nil388 return ref, nil
@@ -405,23 +403,23 @@ func resolveZotfileRef(ref string) (string, error) {
405 if strings.HasSuffix(strings.ToLower(ref), ".zot") {403 if strings.HasSuffix(strings.ToLower(ref), ".zot") {
406 return ref, nil404 return ref, nil
407 }405 }
408- collectionRef := strings.ReplaceAll(ref, "\\", "/")406+ githubRef := strings.ReplaceAll(ref, "\\", "/")
409- parts := strings.Split(collectionRef, "/")407+ parts := strings.Split(githubRef, "/")
410- if len(parts) == 1 && validZotfileCollectionSegment(parts[0]) {408+ if len(parts) == 2 && validGitHubZotfileSegment(parts[0]) && validGitHubZotfileSegment(parts[1]) {
411- return officialZotfileCollection + "/" + parts[0], nil409+ return "https://github.com/" + parts[0] + "/" + parts[1], nil
412 }410 }
413- if len(parts) == 2 && validZotfileCollectionSegment(parts[0]) && validZotfileCollectionSegment(parts[1]) {411+ if len(parts) >= 3 {
414- // Preserve the original official-collection shorthand, where412+ for _, part := range parts {
415- // agents/<name> selects a subdirectory of patriceckhart/agents.413+ if !validGitHubZotfileSegment(part) {
416- if parts[0] == "agents" {414+ return ref, nil
417- return officialZotfileCollection + "/" + parts[1], nil415+ }
418 }416 }
419- return "https://github.com/" + parts[0] + "/" + parts[1], nil417+ return "https://github.com/" + strings.Join(parts, "/"), nil
420 }418 }
421 return ref, nil419 return ref, nil
422 }420 }
423 421
424-func validZotfileCollectionSegment(s string) bool {422+func validGitHubZotfileSegment(s string) bool {
425 return s != "" && s == strings.ToLower(s) && safeAgentName(s) == s423 return s != "" && s == strings.ToLower(s) && safeAgentName(s) == s
426 }424 }
427 425
M packages/agent/zotfile_test.go +10 -7
@@ -162,7 +162,7 @@ func TestLoadZotfileRejectsUnsafeOrCollidingNames(t *testing.T) {
162162 }
163163 }
164164
165-func TestResolveZotfileRefUsesLocalFirstThenOfficialCollection(t *testing.T) {
165+func TestResolveZotfileRefUsesLocalFirstThenGitHubShorthand(t *testing.T) {
166166 dir := t.TempDir()
167167 t.Chdir(dir)
168168 if err := os.Mkdir("local-agent", 0o700); err != nil {
@@ -178,11 +178,13 @@ func TestResolveZotfileRefUsesLocalFirstThenOfficialCollection(t *testing.T) {
178178 }{
179179 {"local-agent", "local-agent"},
180180 {"packed-agent", "packed-agent.zot"},
181- {"remote-agent", officialZotfileCollection + "/remote-agent"},
181+ {"remote-agent", "remote-agent"},
182182 {"missing.zot", "missing.zot"},
183- {"agents/remote-agent", officialZotfileCollection + "/remote-agent"},
184- {`agents\remote-agent`, officialZotfileCollection + "/remote-agent"},
183+ {"agents/remote-agent", "https://github.com/agents/remote-agent"},
184+ {`agents\remote-agent`, "https://github.com/agents/remote-agent"},
185185 {"frkr/zot-archify", "https://github.com/frkr/zot-archify"},
186+ {"acme/agents/reviewer", "https://github.com/acme/agents/reviewer"},
187+ {`acme\agents\reviewers\go`, "https://github.com/acme/agents/reviewers/go"},
186188 {"./missing-agent", "./missing-agent"},
187189 {"Remote-Agent", "Remote-Agent"},
188190 {"https://github.com/acme/agents/example", "https://github.com/acme/agents/example"},
@@ -259,8 +261,9 @@ func TestParseGitHubAgentURL(t *testing.T) {
259261 input string
260262 owner, repo, ref, dir string
261263 }{
262- {"https://github.com/patriceckhart/agents/zot-maintenance", "patriceckhart", "agents", "HEAD", "zot-maintenance"},
263- {"https://github.com/patriceckhart/agents/tree/main/zot-maintenance", "patriceckhart", "agents", "main", "zot-maintenance"},
264+ {"https://github.com/acme/agents/reviewer", "acme", "agents", "HEAD", "reviewer"},
265+ {"https://github.com/acme/agents/tree/main/reviewer", "acme", "agents", "main", "reviewer"},
266+ {"https://github.com/acme/agents/reviewers/go", "acme", "agents", "HEAD", "reviewers/go"},
264267 {"https://github.com/acme/agent.git", "acme", "agent", "HEAD", ""},
265268 }
266269 for _, tt := range tests {
@@ -310,7 +313,7 @@ func TestLoadRemoteZotfileDownloadsTemporaryGitHubArchive(t *testing.T) {
310313 githubArchiveURL = func(_, _, _ string) string { return server.URL }
311314 t.Cleanup(func() { githubArchiveURL = oldArchiveURL })
312315
313- u, _ := url.Parse("https://github.com/patriceckhart/agents/zot-maintenance")
316+ u, _ := url.Parse("https://github.com/acme/agents/zot-maintenance")
314317 zf, cleanup, err := loadRemoteZotfile(u)
315318 if err != nil {
316319 t.Fatal(err)
@@ -162,7 +162,7 @@ func TestLoadZotfileRejectsUnsafeOrCollidingNames(t *testing.T) {
162 }162 }
163 }163 }
164 164
165-func TestResolveZotfileRefUsesLocalFirstThenOfficialCollection(t *testing.T) {165+func TestResolveZotfileRefUsesLocalFirstThenGitHubShorthand(t *testing.T) {
166 dir := t.TempDir()166 dir := t.TempDir()
167 t.Chdir(dir)167 t.Chdir(dir)
168 if err := os.Mkdir("local-agent", 0o700); err != nil {168 if err := os.Mkdir("local-agent", 0o700); err != nil {
@@ -178,11 +178,13 @@ func TestResolveZotfileRefUsesLocalFirstThenOfficialCollection(t *testing.T) {
178 }{178 }{
179 {"local-agent", "local-agent"},179 {"local-agent", "local-agent"},
180 {"packed-agent", "packed-agent.zot"},180 {"packed-agent", "packed-agent.zot"},
181- {"remote-agent", officialZotfileCollection + "/remote-agent"},181+ {"remote-agent", "remote-agent"},
182 {"missing.zot", "missing.zot"},182 {"missing.zot", "missing.zot"},
183- {"agents/remote-agent", officialZotfileCollection + "/remote-agent"},183+ {"agents/remote-agent", "https://github.com/agents/remote-agent"},
184- {`agents\remote-agent`, officialZotfileCollection + "/remote-agent"},184+ {`agents\remote-agent`, "https://github.com/agents/remote-agent"},
185 {"frkr/zot-archify", "https://github.com/frkr/zot-archify"},185 {"frkr/zot-archify", "https://github.com/frkr/zot-archify"},
186+ {"acme/agents/reviewer", "https://github.com/acme/agents/reviewer"},
187+ {`acme\agents\reviewers\go`, "https://github.com/acme/agents/reviewers/go"},
186 {"./missing-agent", "./missing-agent"},188 {"./missing-agent", "./missing-agent"},
187 {"Remote-Agent", "Remote-Agent"},189 {"Remote-Agent", "Remote-Agent"},
188 {"https://github.com/acme/agents/example", "https://github.com/acme/agents/example"},190 {"https://github.com/acme/agents/example", "https://github.com/acme/agents/example"},
@@ -259,8 +261,9 @@ func TestParseGitHubAgentURL(t *testing.T) {
259 input string261 input string
260 owner, repo, ref, dir string262 owner, repo, ref, dir string
261 }{263 }{
262- {"https://github.com/patriceckhart/agents/zot-maintenance", "patriceckhart", "agents", "HEAD", "zot-maintenance"},264+ {"https://github.com/acme/agents/reviewer", "acme", "agents", "HEAD", "reviewer"},
263- {"https://github.com/patriceckhart/agents/tree/main/zot-maintenance", "patriceckhart", "agents", "main", "zot-maintenance"},265+ {"https://github.com/acme/agents/tree/main/reviewer", "acme", "agents", "main", "reviewer"},
266+ {"https://github.com/acme/agents/reviewers/go", "acme", "agents", "HEAD", "reviewers/go"},
264 {"https://github.com/acme/agent.git", "acme", "agent", "HEAD", ""},267 {"https://github.com/acme/agent.git", "acme", "agent", "HEAD", ""},
265 }268 }
266 for _, tt := range tests {269 for _, tt := range tests {
@@ -310,7 +313,7 @@ func TestLoadRemoteZotfileDownloadsTemporaryGitHubArchive(t *testing.T) {
310 githubArchiveURL = func(_, _, _ string) string { return server.URL }313 githubArchiveURL = func(_, _, _ string) string { return server.URL }
311 t.Cleanup(func() { githubArchiveURL = oldArchiveURL })314 t.Cleanup(func() { githubArchiveURL = oldArchiveURL })
312 315
313- u, _ := url.Parse("https://github.com/patriceckhart/agents/zot-maintenance")316+ u, _ := url.Parse("https://github.com/acme/agents/zot-maintenance")
314 zf, cleanup, err := loadRemoteZotfile(u)317 zf, cleanup, err := loadRemoteZotfile(u)
315 if err != nil {318 if err != nil {
316 t.Fatal(err)319 t.Fatal(err)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close