# feat(control-plane): resolve repos by name with --project scope

`41bc806`·

toothbrush·3w ago·4 files·+132 added/-14 removed

repo get/delete and grant repo add/list/remove now accept a repo name
(not just a ULID) when --project <name\|ULID> is given to scope the
lookup — repo names are unique only within a project. A ULID still
passes through unchanged and ignores --project.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

ab8e423ff72fView transcript

[?\
Enhance Entire CLI with Name ResolutionClaude Code·2 steps](/content/gh/entireio/cli/session/b5fd39e9-5894-44f5-99fa-b34bce5b32ba#timeline-ab8e423ff72f/index.html)

## Changes

4

- cmd/entire/cli

- Mgrant.go+24/-7

- Mrepo.go+24/-7

- Mresolveref.go+47

- Mresolveref_test.go+37

```
347 unmodified lines

```go
func newGrantRepoAddCmd() *cobra.Command {
	var provider, providerUserID, role, granteeType string
	var provider, providerUserID, role, granteeType, project string
	cmd := &cobra.Command{
		Use:   "add <repo>",
		Short: "Grant access to a repo",

return err
	}
	return cmd
}

func newGrantRepoListCmd() *cobra.Command {
	return &cobra.Command{
		var project string
		cmd := &cobra.Command{
			Use:   "list <repo>",
			Short: "List repo grants",
			Args:  cobra.ExactArgs(1),
			RunE: func(cmd *cobra.Command, args []string) error {
				return runCoreList(cmd, projectGrantColumns, repoGrantRow, func(ctx context.Context, c *coreapi.Client) ([]coreapi.RepoGrant, error) {
					out, err := c.ListRepoGrants(ctx, coreapi.ListRepoGrantsParams{RepoId: args[0]})
					repoID, err := resolveRepoRef(ctx, c, args[0], project)
					return nil, err
				})
			},
		}
	}
}

```

Mcmd/entire/cli/grant.go+24/-7

```
150 unmodified lines

```

```go
func newRepoGetCmd() *cobra.Command {
	return &cobra.Command{
		var project string
		cmd := &cobra.Command{
			Use:   "get <repo>",
			Short: "Show a repository by name or ULID",
			Args:  cobra.ExactArgs(1),
			RunE: func(cmd *cobra.Command, args []string) error {
				return runCoreObject(cmd, repoColumns, repoRow, func(ctx context.Context, c *coreapi.Client) (*coreapi.Repo, error) {
					sc, err := c.GetRepo(ctx, coreapi.GetRepoParams{RepoId: args[0]})
					return sc, nil
				})
			},
		}
	}
}

func newRepoDeleteCmd() *cobra.Command {
	return &cobra.Command{
		var project string
		cmd := &cobra.Command{
			Use:   "delete <repo>",
			Short: "Delete a repository by name or ULID",
			Args:  cobra.ExactArgs(1),
			RunE: func(cmd *cobra.Command, args []string) error {
				return runCore(cmd, func(ctx context.Context, c *coreapi.Client) error {
					return err
				})
			},
		}
	}
}

// bindRepoProjectFlag wires the shared --project scope used to resolve a repo
// addressed by name (a repo name is unique only within its project). Ignored
// when the repo arg is already a ULID.
func bindRepoProjectFlag(cmd *cobra.Command, project *string) {
	cmd.Flags().StringVar(project, "project", "", "owning project (name or ULID); required when <repo> is a name")
}
```

Mcmd/entire/cli/resolveref.go+47

```
142 unmodified lines

```

```go
func TestPickRepo(t *testing.T) {
	t.Parallel()
	repos := []coreapi.Repo{
		{ID: "01J0REPO000000000000000001", Name: "api"},
		{ID: "01J0REPO000000000000000002", Name: "web"},
	}

t.Run("unique match", func(t *testing.T) {
			t.Parallel()
			got, err := pickRepo(repos, "web")
		}

t.Run("no match", func(t *testing.T) {
			t.Parallel()
			if _, err := pickRepo(repos, "missing"); err == nil {
				}
		}

t.Run("ambiguous", func(t *testing.T) {
			t.Parallel()
			dupes := []coreapi.Repo{
				{ID: "01J0REPO00000000000000000A", Name: "dup"},
				{ID: "01J0REPO00000000000000000B", Name: "dup"},
			}
		}
}

func TestFilterProjectsByName(t *testing.T) {
		
}
```

Mcmd/entire/cli/resolveref_test.go+37

```

145 unmodified lines
