Skip to content

feat: navigation core, remote parsing, layout and clone #1

Closed

Description

@simonostendorf

Goal

gitcd clones a repository into a predictable path under root and the shell can jump to it.
No profiles yet.

Context

  • Trigger: first milestone of the tool, bootstrapped from the design below.
  • Affected: the whole repository, which does not exist as code yet.

Design this milestone implements

Per host settings, with a default template for the rest:

root: ~/Code

layout:
  default: "{host}/{owner}/{repo}"

hosts:
  dev.azure.com:
    layout: "{host}/{org}/{project}/{repo}"
    aliases: [ssh.dev.azure.com, vs-ssh.visualstudio.com]
  github.com:
    aliases: [github-work, github-private]
    protocol: ssh

The alias map is not optional. Two GitHub accounts are driven by SSH host aliases, because
GitHub binds one SSH key to one account, so the parser sees github-work as the host. Without
the map the layout breaks for the case the tool exists for.

Accepted inputs: SSH URL, HTTPS URL, scp style git@host:owner/repo.git, the Azure DevOps
_git form, and the bare host/owner/repo shorthand. The host is lowercased at parse time.
{owner} accepts slashes, for GitLab subgroups.

The binary prints the resolved path on stdout and everything else on stderr, so a shell function
can wrap it. gitcd shell-init zsh|bash|fish prints that snippet and gitcd path <query> is the
plumbing command it calls.

House conventions

  • cmd/gitcd/ holds flag parsing and dispatch only, logic in internal/<area>. No CLI
    framework, flag and hand written dispatch, as in release-me.
  • Standard library plus gopkg.in/yaml.v3, the parser release-me already uses. Any other
    dependency needs a reason in the pull request.
  • Apache-2.0 license header first in every .go file.
  • mise.toml pins every tool, Taskfile.yaml holds one target per check, check aggregates
    and holds no command of its own, CI runs one job per target.

Acceptance criteria

  • Repository scaffolding exists: AGENTS.md, CLAUDE.md holding @AGENTS.md, README.md,
    LICENSE, mise.toml, Taskfile.yaml, .golangci.yaml, .goreleaser.yaml,
    renovate.json, .editorconfig, .gitignore, .github/workflows/, .agent-skills.json.
  • docs/concepts/gitcd.md records problem, goals, non goals, approach, alternatives and open
    questions, carried over from the bootstrap plan.
  • internal/remote parses all five input forms into host, owner, project and repo, resolves
    host aliases, and lowercases the host. One test per form.
  • internal/layout renders a template to a path and maps a path back to a remote.
  • internal/config loads ~/.gitcd.yaml, falls back to $XDG_CONFIG_HOME/gitcd/config.yaml,
    applies defaults and rejects an unknown key with a named error.
  • gitcd clone <url|shorthand> clones into the rendered path and prints that path on stdout.
  • gitcd clone is idempotent: a target that exists with the same remote prints the path and
    exits 0, and a target that exists with a different remote fails with both remotes named.
  • gitcd path <query> resolves an exact repository name or a host/owner/repo to its path.
  • gitcd shell-init zsh|bash|fish prints a working wrapper function.
  • gitcd version prints the version, set at build time.
  • Every command supports --dry-run where it writes.
  • Tests build git repositories under a temporary directory with GIT_CONFIG_GLOBAL,
    GIT_CONFIG_NOSYSTEM=1 and a controlled HOME. No network.
  • task check passes.
  • The bootstrap PLAN.md is deleted, its content now living in this issue series and in
    docs/concepts/gitcd.md.

Out of scope

  • Profiles, identity and anything writing git config. That is the next milestone.
  • list, cd, fuzzy matching, doctor, adopt, status, sync.
  • The landing page at gitcd.ostendorf.cloud.

Open question to resolve while implementing

  • Azure DevOps SSH remotes are assumed to use host ssh.dev.azure.com with path
    v3/{org}/{project}/{repo}, and HTTPS dev.azure.com/{org}/{project}/_git/{repo}. Unverified.
    Confirm against a real remote before fixing the parser's behaviour.

Activity

  1. added
    ai: readyScoped + approved for an AI agent to pick up
    ai: workingAn AI agent is implementing (incl. committed but not yet pushed)
    and removed
    ai: readyScoped + approved for an AI agent to pick up
    ai: workingAn AI agent is implementing (incl. committed but not yet pushed)
    on Nov 13, 2026
  2. simonostendorf commented on Nov 13, 2026

    @simonostendorf
    MemberAuthor

    Implemented on feat/1-navigation-core, draft pull request #6.

    • internal/remote, internal/layout, internal/config, internal/git and internal/shell
      are in place, with cmd/gitcd dispatching clone, path, shell-init and version.
    • Repository scaffolding and the toolchain are pinned, one task target per check and one CI job
      per target.
    • docs/concepts/gitcd.md carries the design and the decisions.
    • task check exit 0: ten targets green, six test packages ok with -race.
    • One dependency, gopkg.in/yaml.v3.
    • The remote is read through git config --get rather than git remote get-url, which expands
      an insteadOf rewrite and broke clone idempotency. Regression tested.
    • The Azure DevOps URL forms stayed unverified against a real remote, as this issue flagged.
      Worth confirming before feat: identity profiles applied per remote #2 builds rules on them.
  3. added
    ai: reviewingAn AI agent is reviewing the pushed work
    ai: changes requestedAI review requested changes - back to the implement loop
    and removed
    ai: reviewingAn AI agent is reviewing the pushed work
    on Nov 13, 2026
  4. added
    ai: reviewingAn AI agent is reviewing the pushed work
    ai: doneAI-reviewed and accepted
    and removed
    ai: changes requestedAI review requested changes - back to the implement loop
    ai: reviewingAn AI agent is reviewing the pushed work
    on Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai: doneAI-reviewed and acceptedfeatureNew feature or capabilitystack: goRelated to Go code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions