Importing from GitHub
There are two ways to get an existing repository into neosource, and a separate opt-in for keeping its issues in sync afterwards.
Start at /new.
Importing code
Section titled “Importing code”From a public Git URL
Section titled “From a public Git URL”The simplest path, and it is not GitHub-specific: paste any public HTTPS Git URL and neosource clones it.
POST /api/imports/urlNo OAuth, no token, no account linkage. The URL is validated when the import is queued — it must be HTTPS, must not carry embedded credentials, and must resolve to a publicly routable host.
Use this for public repositories, or for sources other than GitHub.
Authenticated GitHub import
Section titled “Authenticated GitHub import”Link your GitHub identity and import by owner/name instead of a URL. This is
what you need for private repositories, and it avoids the rate limits that
apply to anonymous clones.
GET /api/github/repos # list repositories you can importPOST /api/github/imports # start an importThe import runs with your stored GitHub OAuth token. Because it is addressed by
owner/name rather than a free-form URL, there is no user-supplied URL in the
clone path at all.
The web UI wraps this at /onboarding/github.
Watching an import
Section titled “Watching an import”GET /api/repos/{owner}/{repo}/import-statusSyncing issues
Section titled “Syncing issues”Importing brings the code. Issues, comments and labels are a separate opt-in, available only for repositories that came in through the authenticated GitHub import — a repository imported from a plain URL has no GitHub identity to sync against.
POST /api/repos/{owner}/{repo}/github-sync # enableGET /api/repos/{owner}/{repo}/github-sync # statusor in the UI at /<owner>/<repo>/settings/github-sync.
Two modes:
| Mode | Behaviour |
|---|---|
| Synced | Field-split. GitHub owns issue title, body, open/closed state, comments and labels. neosource owns the planning overlay on top — lane, priority, cycle, assignees. |
| Mirror (read-only) | A read-only mirror of the GitHub metadata, with no overlay editing. |
The split in Synced mode is the point: GitHub stays the system of record for the conversation, while the planning layer that GitHub does not have lives in neosource and does not fight it.
Requirements and limits
Section titled “Requirements and limits”Enabling sync requires:
- repo admin on the neosource repository,
- a linked GitHub identity with a stored access token — that account becomes the importer whose token the backfill and subsequent polls run on,
- a repository that was imported from GitHub, and
- a repository with no natively-created issues or pull requests yet.
That last one is a hard constraint, not a soft preference. Enabling sync reserves the issue-numbering band, and existing content cannot be renumbered afterwards — so sync can only be turned on for a freshly imported repository. Decide before you start filing issues.
If a sync exhausts its failure budget it enters an error state. Calling the
enable endpoint again re-arms it: the state returns to backfilling and the
backfill resumes from where its cursors left off, rather than starting over.
After importing: CI does not come across
Section titled “After importing: CI does not come across”Your workflows will not run. neosource reads .neosource/workflows/, and
.github/workflows/ is ignored entirely — with no warning. An imported
repository with a full set of GitHub Actions workflows simply has no CI until
you move and adapt the files.
Start with Coming from GitHub Actions, which covers
what carries over unchanged and what has to be rewritten. The main rewrite is
that jobs declare tools with packages: rather than choosing a container image
— see the job environment.