Move your projects with an AI agent
After the copy from Nexus, each project still names Nexus. A coding agent, such as Claude Code, can move a project with you.
The agent changes the files. It asks you for the few steps that need a person.
To make the changes yourself, see Move your projects by hand.
Choose the prompt
Section titled “Choose the prompt”- Gradle or Maven
- npm, pnpm, Yarn or Bun
- Python
- Rust and Cargo
- .NET and NuGet
- Docker and Helm
- Debian or raw files
- Download addresses only
- Full switch-over with publishing
-
Copy the prompt below.
-
Fill in its first lines: your two server addresses, and the name of each repository in Nexus and in Telesphorepo. The Repositories page lists the names. A lock after a name means it is private.
-
Open the agent in the project folder, and paste the prompt.
-
Read the changes before you commit them.
Gradle or Maven: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- maven-public -> maven-public- maven-releases -> maven-releasesPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in pom.xml, .mvn/maven.config, every settings.xml, build.gradle(.kts), settings.gradle(.kts) (pluginManagement, dependencyResolutionManagement), gradle.properties, gradle/*.gradle(.kts), buildSrc/, build-logic/, init scripts and gradle/wrapper/gradle-wrapper.properties, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Also show me what ~/.m2/settings.xml, ~/.gradle/gradle.properties and ~/.gradle/init.d/ on this computer name. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. https://nexus.example.com/repository/<nexus name>/ becomes https://repo.example.com/maven/<telesphorepo name>. Only the prefix changes; the files keep their paths. A <mirror> with <mirrorOf>*</mirrorOf> points at a Telesphorepo group. A distributionUrl on a Nexus raw repository becomes https://repo.example.com/raw/<name>/<path>; keep distributionSha256Sum.3. Lockfiles: Gradle lockfiles and gradle/verification-metadata.xml hold no addresses. Keep them.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in ORG_GRADLE_PROJECT_<name>Username and ORG_GRADLE_PROJECT_<name>Password for Gradle, and TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN for Maven, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. Gradle: in the maven { } block, name = "<name>" and credentials(PasswordCredentials::class) (Groovy: credentials(PasswordCredentials)); <name> is the repository name as a Gradle identifier (my-libs is myLibs). Maven: a <server> whose <id> is the <id> of the repository or mirror, with ${env.TELESPHOREPO_READ_USER} and ${env.TELESPHOREPO_READ_TOKEN}, in ~/.m2/settings.xml and in a settings file of the project that CI passes with -s.5. Watch for these. A hosted repository holds only its own packages: keep mavenCentral(), or use a group with a proxy of Maven Central. A Maven group merges the versions of all its members, as Nexus does. Maven refuses http:// addresses other than localhost; Gradle needs isAllowInsecureProtocol = true for one.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (./gradlew build --refresh-dependencies, or mvn -U -Dmaven.repo.local=<new empty folder> verify), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.Gradle or Maven: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- maven-public -> maven-public- maven-releases -> maven-releasesPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, maven-releases-rehearsal, and move to maven-releases after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted Maven repository named maven-releases-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories maven-releases-rehearsal and maven-releases. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in pom.xml, .mvn/maven.config, every settings.xml, build.gradle(.kts), settings.gradle(.kts) (pluginManagement, dependencyResolutionManagement), gradle.properties, gradle/*.gradle(.kts), buildSrc/, build-logic/, init scripts and gradle/wrapper/gradle-wrapper.properties, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Also show me what ~/.m2/settings.xml, ~/.gradle/gradle.properties and ~/.gradle/init.d/ on this computer name. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. https://nexus.example.com/repository/<nexus name>/ becomes https://repo.example.com/maven/<telesphorepo name>. Only the prefix changes; the files keep their paths. A <mirror> with <mirrorOf>*</mirrorOf> points at a Telesphorepo group. A distributionUrl on a Nexus raw repository becomes https://repo.example.com/raw/<name>/<path>; keep distributionSha256Sum.4. Lockfiles: Gradle lockfiles and gradle/verification-metadata.xml hold no addresses. Keep them.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in ORG_GRADLE_PROJECT_<name>Username and ORG_GRADLE_PROJECT_<name>Password for Gradle, and TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN for Maven, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. Gradle: in the maven { } block, name = "<name>" and credentials(PasswordCredentials::class) (Groovy: credentials(PasswordCredentials)); <name> is the repository name as a Gradle identifier (my-libs is myLibs). Maven: a <server> whose <id> is the <id> of the repository or mirror, with ${env.TELESPHOREPO_READ_USER} and ${env.TELESPHOREPO_READ_TOKEN}, in ~/.m2/settings.xml and in a settings file of the project that CI passes with -s.6. Watch for these. A hosted repository holds only its own packages: keep mavenCentral(), or use a group with a proxy of Maven Central. A Maven group merges the versions of all its members, as Nexus does. Maven refuses http:// addresses other than localhost; Gradle needs isAllowInsecureProtocol = true for one.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (./gradlew build --refresh-dependencies, or mvn -U -Dmaven.repo.local=<new empty folder> verify), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: the <distributionManagement> entries and <server> credentials for Nexus, the Nexus staging plugins (nexus-staging-maven-plugin, io.github.gradle-nexus.publish-plugin) that target our Nexus, and the Nexus repository in Gradle's publishing { repositories { } } (gradle publish publishes to every repository there). Keep the maven-publish plugin, the publications, group and version. telesphorepo publish runs mvn deploy (or ./mvnw) with the repository as the target, or gradle publish (or ./gradlew) with an init script that adds the repository; the build files keep no publish address. List the CI secrets nothing uses now.11. Write telesphorepo.toml next to pom.xml or the Gradle settings file. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "maven-releases-rehearsal" If the folder has both Maven and Gradle files, add kind = "maven" or kind = "gradle".12. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, actions/setup-java@v6 (distribution: temurin, java-version: the project's Java version, such as 21) with no build step, then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish Jenkins: keep the build stage (./gradlew build, on Windows .\gradlew.bat build; or mvn -B verify), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variables from secrets.13. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish. If the server says my account may not publish, ask me for Publish on maven-releases-rehearsal.14. Verify: in a new temporary folder, write a minimal Gradle or Maven build that depends on the group:artifact:version you published, from https://repo.example.com/maven/maven-releases-rehearsal, and build it with an empty cache. Then delete the folder.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to maven-releases, check that the CI pipeline lists maven-releases, publish once, then delete maven-releases-rehearsal.npm, pnpm, Yarn or Bun: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- npm-group -> npm-group- npm-hosted -> npm-hostedPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in .npmrc (the project's and ~/.npmrc), .yarnrc.yml, .yarnrc (Yarn 1), bunfig.toml, package.json (publishConfig, scripts), the lockfiles and the registry-url input of actions/setup-node, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. https://nexus.example.com/repository/<nexus name>/ becomes https://repo.example.com/npm/<telesphorepo name>/, with the trailing slash. Scoped registries (@acme:registry=) change the same way; Yarn 2 and later name them in npmRegistryServer and npmScopes. Remove the Nexus _auth, always-auth and email lines. Bun reads .npmrc, and bunfig.toml can set [install] registry and scopes. On a hosted repository, Yarn 4 needs npmMinimalAgeGate: 0, or it installs a version only once it is a week old; on a group or a proxy, list our own packages in npmPreapprovedPackages instead. A plain http:// server needs its host in unsafeHttpWhitelist of Yarn.3. Lockfiles: in package-lock.json, a Yarn 1 yarn.lock, pnpm-lock.yaml and bun.lock, change the prefix https://nexus.example.com/repository/<nexus name>/ to https://repo.example.com/npm/<telesphorepo name>/. The tarballs keep their paths (<name>/-/<file>.tgz) and their integrity. A Yarn 2+ yarn.lock holds no address. Then run the frozen install of the tool: npm ci, pnpm install --frozen-lockfile, yarn install --immutable or bun install --frozen-lockfile.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it in NPM_TOKEN, here and as a CI secret. Tell me this name first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variable in: .npmrc gets //repo.example.com/npm/<name>/:_authToken=${NPM_TOKEN}; .yarnrc.yml gets npmAlwaysAuth: true and npmAuthToken: "${NPM_TOKEN}". In CI, the install step gets NPM_TOKEN from a secret.5. Watch for these. In a Telesphorepo npm group, the first member that has a package name owns it, and the group serves every version of that name from that member only; Nexus merges them. If the project needs versions of one name from two members, tell me. Telesphorepo does not serve npm audit: point an audit step at --registry=https://registry.npmjs.org/, or tell me.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (delete node_modules, then run the frozen install with an empty cache; for npm: npm ci --cache <new empty folder>), and check that every download comes from repo.example.com. If your shell lacks the token variable, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.npm, pnpm, Yarn or Bun: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- npm-group -> npm-group- npm-hosted -> npm-hostedPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, npm-hosted-rehearsal, and move to npm-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted npm repository named npm-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories npm-hosted-rehearsal and npm-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in .npmrc (the project's and ~/.npmrc), .yarnrc.yml, .yarnrc (Yarn 1), bunfig.toml, package.json (publishConfig, scripts), the lockfiles and the registry-url input of actions/setup-node, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. https://nexus.example.com/repository/<nexus name>/ becomes https://repo.example.com/npm/<telesphorepo name>/, with the trailing slash. Scoped registries (@acme:registry=) change the same way; Yarn 2 and later name them in npmRegistryServer and npmScopes. Remove the Nexus _auth, always-auth and email lines. Bun reads .npmrc, and bunfig.toml can set [install] registry and scopes. On a hosted repository, Yarn 4 needs npmMinimalAgeGate: 0, or it installs a version only once it is a week old; on a group or a proxy, list our own packages in npmPreapprovedPackages instead. A plain http:// server needs its host in unsafeHttpWhitelist of Yarn.4. Lockfiles: in package-lock.json, a Yarn 1 yarn.lock, pnpm-lock.yaml and bun.lock, change the prefix https://nexus.example.com/repository/<nexus name>/ to https://repo.example.com/npm/<telesphorepo name>/. The tarballs keep their paths (<name>/-/<file>.tgz) and their integrity. A Yarn 2+ yarn.lock holds no address. Then run the frozen install of the tool: npm ci, pnpm install --frozen-lockfile, yarn install --immutable or bun install --frozen-lockfile.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it in NPM_TOKEN, here and as a CI secret. Tell me this name first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variable in: .npmrc gets //repo.example.com/npm/<name>/:_authToken=${NPM_TOKEN}; .yarnrc.yml gets npmAlwaysAuth: true and npmAuthToken: "${NPM_TOKEN}". In CI, the install step gets NPM_TOKEN from a secret.6. Watch for these. In a Telesphorepo npm group, the first member that has a package name owns it, and the group serves every version of that name from that member only; Nexus merges them. If the project needs versions of one name from two members, tell me. Telesphorepo does not serve npm audit: point an audit step at --registry=https://registry.npmjs.org/, or tell me.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (delete node_modules, then run the frozen install with an empty cache; for npm: npm ci --cache <new empty folder>), and check that every download comes from repo.example.com. If your shell lacks the token variable, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: publishConfig.registry, the Nexus publish auth lines, and the npm publish steps of CI with their secrets. telesphorepo publish picks the tool by the lockfile: pnpm publish (pnpm-lock.yaml), yarn npm publish (yarn.lock), bun publish (bun.lock), else npm publish. List the CI secrets nothing uses now.11. Write telesphorepo.toml next to package.json. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "npm-hosted-rehearsal" In a workspace, ask me which packages publish, and put a telesphorepo.toml in each of their folders.12. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, then the steps of the tool: npm: actions/setup-node@v5 (node-version: lts/*) and run: npm ci; pnpm: pnpm/action-setup@v4, actions/setup-node@v5 and run: pnpm install --frozen-lockfile; Yarn: actions/setup-node@v5 and run: corepack enable && yarn install --immutable; Bun: oven-sh/setup-bun@v2 and run: bun install --frozen-lockfile. Then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish Jenkins: keep the build stage (the same install command), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variable from secrets.13. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish. If the server says my account may not publish, ask me for Publish on npm-hosted-rehearsal.14. Verify: in a new temporary folder, run npm init -y, write an .npmrc with the registry https://repo.example.com/npm/npm-hosted-rehearsal/, and run npm install <package>@<version>. Then delete the folder.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to npm-hosted, check that the CI pipeline lists npm-hosted, publish once, then delete npm-hosted-rehearsal.Python: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- pypi-group -> pypi-group- pypi-hosted -> pypi-hostedPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in pip.conf or pip.ini (the project's, ~/.config/pip/pip.conf, /etc/pip.conf), requirements*.txt and constraints files (--index-url, --extra-index-url, --trusted-host), pyproject.toml ([[tool.uv.index]], [[tool.poetry.source]], [tool.pdm]), uv.toml, poetry.toml, setup.cfg, tox.ini, noxfile.py, .pypirc, and PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, UV_INDEX_URL or UV_DEFAULT_INDEX, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. https://nexus.example.com/repository/<nexus name>/simple/ (with or without simple/) becomes https://repo.example.com/pypi/<telesphorepo name>/simple/. On a plain http:// server, pip needs trusted-host = <host> and uv needs allow-insecure-host.3. Lockfiles: uv.lock and poetry.lock hold file addresses whose paths differ between Nexus and Telesphorepo, so run the lock command instead of editing them: uv lock, or poetry lock (Poetry 1: poetry lock --no-update). Then check git diff: the same versions and hashes, other addresses only. In requirements files with --hash, change only the index lines.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in PIP_INDEX_URL for pip, UV_INDEX_<NAME>_USERNAME and UV_INDEX_<NAME>_PASSWORD for uv, or POETRY_HTTP_BASIC_<SOURCE>_USERNAME and POETRY_HTTP_BASIC_<SOURCE>_PASSWORD for Poetry, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in: pip reads credentials from the address, so the whole address with my username and the token goes in PIP_INDEX_URL, and the files keep the address without credentials. For uv, <NAME> is the index name in upper case, other characters as _; for Poetry, <SOURCE> is the source name the same way.5. Watch for these. A hosted repository holds only our own packages: their dependencies need a group with a PyPI proxy, or PyPI itself. In a Telesphorepo PyPI group, the first member that has a project name owns it, with every file of that project; Nexus merges them. If the project needs files of one name from two members, tell me.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (a new virtual environment, then pip install --no-cache-dir -r requirements.txt, uv sync --no-cache, or poetry install with a new cache folder), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.Python: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- pypi-group -> pypi-group- pypi-hosted -> pypi-hostedPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, pypi-hosted-rehearsal, and move to pypi-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted PyPI repository named pypi-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories pypi-hosted-rehearsal and pypi-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in pip.conf or pip.ini (the project's, ~/.config/pip/pip.conf, /etc/pip.conf), requirements*.txt and constraints files (--index-url, --extra-index-url, --trusted-host), pyproject.toml ([[tool.uv.index]], [[tool.poetry.source]], [tool.pdm]), uv.toml, poetry.toml, setup.cfg, tox.ini, noxfile.py, .pypirc, and PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, UV_INDEX_URL or UV_DEFAULT_INDEX, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. https://nexus.example.com/repository/<nexus name>/simple/ (with or without simple/) becomes https://repo.example.com/pypi/<telesphorepo name>/simple/. On a plain http:// server, pip needs trusted-host = <host> and uv needs allow-insecure-host.4. Lockfiles: uv.lock and poetry.lock hold file addresses whose paths differ between Nexus and Telesphorepo, so run the lock command instead of editing them: uv lock, or poetry lock (Poetry 1: poetry lock --no-update). Then check git diff: the same versions and hashes, other addresses only. In requirements files with --hash, change only the index lines.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in PIP_INDEX_URL for pip, UV_INDEX_<NAME>_USERNAME and UV_INDEX_<NAME>_PASSWORD for uv, or POETRY_HTTP_BASIC_<SOURCE>_USERNAME and POETRY_HTTP_BASIC_<SOURCE>_PASSWORD for Poetry, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in: pip reads credentials from the address, so the whole address with my username and the token goes in PIP_INDEX_URL, and the files keep the address without credentials. For uv, <NAME> is the index name in upper case, other characters as _; for Poetry, <SOURCE> is the source name the same way.6. Watch for these. A hosted repository holds only our own packages: their dependencies need a group with a PyPI proxy, or PyPI itself. In a Telesphorepo PyPI group, the first member that has a project name owns it, with every file of that project; Nexus merges them. If the project needs files of one name from two members, tell me.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (a new virtual environment, then pip install --no-cache-dir -r requirements.txt, uv sync --no-cache, or poetry install with a new cache folder), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: the use of .pypirc, twine upload, uv publish and publish-url, poetry publish -r and the Poetry repository config for Nexus, and their CI secrets. telesphorepo publish runs poetry build (with [tool.poetry]), uv build (with uv.lock) or python -m build, then uploads every wheel and sdist. List the CI secrets nothing uses now.11. Write telesphorepo.toml next to pyproject.toml or setup.py. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "pypi-hosted-rehearsal"12. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, then the steps of the tool: uv: astral-sh/setup-uv@v7; Poetry: actions/setup-python@v6 (python-version: 3.x) and run: pipx install poetry; pip: actions/setup-python@v6 and run: python -m pip install build. Then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish Jenkins: keep the build stage (none for uv and Poetry, but the agent needs the tool installed; for pip, python3 -m pip install --user build), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variables from secrets.13. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish (telesphorepo publish dist/*.whl uploads files that are built already). If the server says my account may not publish, ask me for Publish on pypi-hosted-rehearsal.14. Verify: in a new temporary virtual environment, run pip install --index-url https://repo.example.com/pypi/pypi-hosted-rehearsal/simple/ --extra-index-url https://pypi.org/simple/ <package>==<version>. Then delete it.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to pypi-hosted, check that the CI pipeline lists pypi-hosted, publish once, then delete pypi-hosted-rehearsal.Rust and Cargo: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- cargo-group -> cargo-group- cargo-hosted -> cargo-hostedPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in .cargo/config.toml (the project's and ~/.cargo/config.toml), Cargo.toml (registry = of dependencies, publish =), Cargo.lock and CARGO_REGISTRIES_* variables, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. The index becomes sparse+https://repo.example.com/cargo/<telesphorepo name>/index/. Keep the registry names that Cargo.toml uses, and change only index in [registries.<name>]. A proxy or a group of crates.io also takes [source.crates-io] replace-with = "<name>".3. Lockfiles: in Cargo.lock, change each source = "sparse+<Nexus index>" (or registry+) to the Telesphorepo index, exactly as in the config. Keep every checksum. Then run cargo fetch --locked.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it in CARGO_REGISTRIES_<NAME>_TOKEN (the registry name in upper case, - as _), here and as a CI secret. Tell me this name first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variable in: the registry gets credential-provider = "cargo:token", and Cargo reads the token from the variable. This needs Cargo 1.74 or later.5. Watch for these. In a Telesphorepo Cargo group, the first member that has a crate name owns it, and the group serves every version of that name from that member only.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (cargo build --locked with a new, empty CARGO_HOME), and check that every download comes from repo.example.com. If your shell lacks the token variable, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.Rust and Cargo: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- cargo-group -> cargo-group- cargo-hosted -> cargo-hostedPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, cargo-hosted-rehearsal, and move to cargo-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted Cargo repository named cargo-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories cargo-hosted-rehearsal and cargo-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in .cargo/config.toml (the project's and ~/.cargo/config.toml), Cargo.toml (registry = of dependencies, publish =), Cargo.lock and CARGO_REGISTRIES_* variables, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. The index becomes sparse+https://repo.example.com/cargo/<telesphorepo name>/index/. Keep the registry names that Cargo.toml uses, and change only index in [registries.<name>]. A proxy or a group of crates.io also takes [source.crates-io] replace-with = "<name>".4. Lockfiles: in Cargo.lock, change each source = "sparse+<Nexus index>" (or registry+) to the Telesphorepo index, exactly as in the config. Keep every checksum. Then run cargo fetch --locked.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it in CARGO_REGISTRIES_<NAME>_TOKEN (the registry name in upper case, - as _), here and as a CI secret. Tell me this name first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variable in: the registry gets credential-provider = "cargo:token", and Cargo reads the token from the variable. This needs Cargo 1.74 or later.6. Watch for these. In a Telesphorepo Cargo group, the first member that has a crate name owns it, and the group serves every version of that name from that member only.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (cargo build --locked with a new, empty CARGO_HOME), and check that every download comes from repo.example.com. If your shell lacks the token variable, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: the cargo publish --registry <nexus> steps and the Nexus tokens. Where Cargo.toml has publish = [...] with the Nexus registry, set publish = ["telesphorepo"]: the CLI publishes with --registry telesphorepo, and Cargo refuses a registry that the list does not name. Do not remove the key, or a plain cargo publish goes to crates.io. List the CI secrets nothing uses now.11. Write telesphorepo.toml next to Cargo.toml. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "cargo-hosted-rehearsal"12. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, dtolnay/rust-toolchain@stable with no build step, then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish Jenkins: keep the build stage (cargo test), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variable from secrets.13. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish. If the server says my account may not publish, ask me for Publish on cargo-hosted-rehearsal.14. Verify: in a new temporary folder, run cargo new verify, write a .cargo/config.toml with the registry of cargo-hosted-rehearsal, run cargo add <crate>@<version> --registry <name>, then cargo build. Then delete the folder.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to cargo-hosted, check that the CI pipeline lists cargo-hosted, publish once, then delete cargo-hosted-rehearsal..NET and NuGet: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- nuget-group -> nuget-group- nuget-hosted -> nuget-hostedPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in nuget.config or NuGet.Config (the solution folder, its parents and the user's), Directory.Build.props and .targets (RestoreSources, RestoreAdditionalProjectSources), *.csproj and *.fsproj, dotnet nuget add source, --source and the source-url input of actions/setup-dotnet, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. https://nexus.example.com/repository/<nexus name>/index.json (or the v2 address without index.json) becomes https://repo.example.com/nuget/<telesphorepo name>/index.json. Keep the source keys, so packageSourceMapping and the credentials still match. A source on plain http:// needs allowInsecureConnections="true".3. Lockfiles: packages.lock.json holds no address. Keep it.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in NUGET_USERNAME and NUGET_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in: nuget.config gets <packageSourceCredentials> under the source key (a key that starts with a digit is written _x003N_...), with Username %NUGET_USERNAME% and ClearTextPassword %NUGET_TOKEN%.5. Watch for these. In a Telesphorepo NuGet group, the first member that has a package id owns it, and the group serves every version of that id from that member only; Nexus merges them. If the project needs versions of one id from two members, tell me.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (dotnet restore --no-cache --force, then dotnet build), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about..NET and NuGet: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- nuget-group -> nuget-group- nuget-hosted -> nuget-hostedPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, nuget-hosted-rehearsal, and move to nuget-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted NuGet repository named nuget-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories nuget-hosted-rehearsal and nuget-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in nuget.config or NuGet.Config (the solution folder, its parents and the user's), Directory.Build.props and .targets (RestoreSources, RestoreAdditionalProjectSources), *.csproj and *.fsproj, dotnet nuget add source, --source and the source-url input of actions/setup-dotnet, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. https://nexus.example.com/repository/<nexus name>/index.json (or the v2 address without index.json) becomes https://repo.example.com/nuget/<telesphorepo name>/index.json. Keep the source keys, so packageSourceMapping and the credentials still match. A source on plain http:// needs allowInsecureConnections="true".4. Lockfiles: packages.lock.json holds no address. Keep it.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in NUGET_USERNAME and NUGET_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in: nuget.config gets <packageSourceCredentials> under the source key (a key that starts with a digit is written _x003N_...), with Username %NUGET_USERNAME% and ClearTextPassword %NUGET_TOKEN%.6. Watch for these. In a Telesphorepo NuGet group, the first member that has a package id owns it, and the group serves every version of that id from that member only; Nexus merges them. If the project needs versions of one id from two members, tell me.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (dotnet restore --no-cache --force, then dotnet build), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: the dotnet nuget push or nuget push steps to Nexus, <apikeys>, and the API key secrets. telesphorepo publish runs dotnet pack -c Release and pushes each package. List the CI secrets nothing uses now.11. Write telesphorepo.toml next to the solution or project file. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "nuget-hosted-rehearsal"12. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, actions/setup-dotnet@v5 (dotnet-version: the project's SDK version, such as 10.0.x) with no build step, then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish Jenkins: keep the build stage (dotnet build -c Release), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variables from secrets.13. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish (telesphorepo publish <file>.nupkg pushes packages that are built already). If the server says my account may not publish, ask me for Publish on nuget-hosted-rehearsal.14. Verify: in a new temporary folder, run dotnet new console, write a nuget.config with the source https://repo.example.com/nuget/nuget-hosted-rehearsal/index.json, and run dotnet add package <id> --version <version>. Then delete the folder.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to nuget-hosted, check that the CI pipeline lists nuget-hosted, publish once, then delete nuget-hosted-rehearsal.Docker and Helm: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- docker-hosted -> docker-hosted- docker-hub -> docker-hubNexus Docker hosts and ports (host or port -> Nexus name):- nexus.example.com:8082 -> docker-hosted- nexus.example.com:8083 -> docker-hubPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host, for /repository/ and for the Nexus Docker hosts and ports. Look in Dockerfile* (FROM, COPY --from), compose files (image:), Kubernetes manifests and Kustomize (image:, images:, imagePullSecrets), Helm Chart.yaml (dependencies), Chart.lock, values*.yaml (image.registry, image.repository), helmfile, skaffold, Tiltfile, devcontainer files, and docker login, docker pull, helm registry login and helm repo add, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. Telesphorepo serves the registry at the root of its host, and the repository name is the first part of the image name. nexus.example.com:8082/team/app:1.0 becomes repo.example.com/docker-hosted/team/app:1.0. Through a proxy of Docker Hub, an official image is repo.example.com/docker-hub/nginx:1.27 (or library/nginx). The manifests are the same, so each @sha256: digest stays valid. A plain http:// server needs its host in insecure-registries of /etc/docker/daemon.json. Helm charts are OCI artifacts in Docker repositories: a chart dependency on a Nexus Helm repository becomes oci://repo.example.com/<name>, and its helm repo add line goes. The Nexus copy does not include Nexus Helm repositories, so ask me which Docker repository holds the charts.3. Lockfiles: after a change to the Chart.yaml dependencies, run helm dependency update to renew Chart.lock.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. In CI and on servers, log in from the secrets: printf '%s' "$TELESPHOREPO_READ_TOKEN" | docker login repo.example.com -u "$TELESPHOREPO_READ_USER" --password-stdin For Kubernetes, I make the pull secret (kubectl create secret docker-registry ...); the manifests name only the secret. On my computer, use the credential helper of the CLI instead. If telesphorepo version fails, install the CLI (curl -fsSL https://repo.example.com/install.sh | sh, or on Windows irm https://repo.example.com/install.ps1 | iex). Run telesphorepo login https://repo.example.com; it prints a link and a code, then waits. ME: give me the link and the code; I open the link, sign in, check the code and click Approve device with my second step. Then add "credHelpers": {"repo.example.com": "telesphorepo"} to ~/.docker/config.json, keeping its other keys. Docker, Podman, Helm and ORAS then pull what my account can read, with no docker login.5. Watch for these. If the server is behind Cloudflare, each image layer must be under 100 MB for a push; tell me about larger layers.6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (remove the local images with docker image rm, pull each image again with docker compose pull or docker pull, and run docker build --pull --no-cache), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.7. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.Docker and Helm: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- docker-hosted -> docker-hosted- docker-hub -> docker-hubNexus Docker hosts and ports (host or port -> Nexus name):- nexus.example.com:8082 -> docker-hosted- nexus.example.com:8083 -> docker-hubPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, docker-hosted-rehearsal, and move to docker-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted Docker repository named docker-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories docker-hosted-rehearsal and docker-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host, for /repository/ and for the Nexus Docker hosts and ports. Look in Dockerfile* (FROM, COPY --from), compose files (image:), Kubernetes manifests and Kustomize (image:, images:, imagePullSecrets), Helm Chart.yaml (dependencies), Chart.lock, values*.yaml (image.registry, image.repository), helmfile, skaffold, Tiltfile, devcontainer files, and docker login, docker pull, helm registry login and helm repo add, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. Telesphorepo serves the registry at the root of its host, and the repository name is the first part of the image name. nexus.example.com:8082/team/app:1.0 becomes repo.example.com/docker-hosted/team/app:1.0. Through a proxy of Docker Hub, an official image is repo.example.com/docker-hub/nginx:1.27 (or library/nginx). The manifests are the same, so each @sha256: digest stays valid. A plain http:// server needs its host in insecure-registries of /etc/docker/daemon.json. Helm charts are OCI artifacts in Docker repositories: a chart dependency on a Nexus Helm repository becomes oci://repo.example.com/<name>, and its helm repo add line goes. The Nexus copy does not include Nexus Helm repositories, so ask me which Docker repository holds the charts.4. Lockfiles: after a change to the Chart.yaml dependencies, run helm dependency update to renew Chart.lock.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. In CI and on servers, log in from the secrets: printf '%s' "$TELESPHOREPO_READ_TOKEN" | docker login repo.example.com -u "$TELESPHOREPO_READ_USER" --password-stdin For Kubernetes, I make the pull secret (kubectl create secret docker-registry ...); the manifests name only the secret. On my computer, the credential helper of steps 8 to 10 does the pulls.6. Watch for these. If the server is behind Cloudflare, each image layer must be under 100 MB for a push; tell me about larger layers.7. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Build with an empty cache (remove the local images with docker image rm, pull each image again with docker compose pull or docker pull, and run docker build --pull --no-cache), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run the build and send you the output.8. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.9. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.10. Remove the Nexus publishing: docker login to Nexus, the Nexus push credentials, and helm push or curl uploads to Nexus. Images publish with docker push repo.example.com/<repo>/<image>:<tag>, and the credential helper gives Docker the publish token: after I say yes, add "credHelpers": {"repo.example.com": "telesphorepo"} to ~/.docker/config.json, keeping its other keys (telesphorepo login does not add it; telesphorepo status shows it). Images need no telesphorepo.toml. A chart folder gets one, and telesphorepo publish runs helm package, then helm push. List the CI secrets nothing uses now.11. For a Helm chart only: write telesphorepo.toml next to Chart.yaml. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "docker-hosted-rehearsal"12. CI for an image. GitHub Actions: the job gets permissions: id-token: write (keep contents: read), and these steps (change app to the image name): - uses: actions/checkout@v7 - run: docker build -t "repo.example.com/docker-hosted-rehearsal/app:$GITHUB_SHA" . - run: curl -fsSL https://repo.example.com/install.sh | sh - name: Publish to docker-hosted-rehearsal run: | export DOCKER_CONFIG="$(mktemp -d)" printf '%s\n' '{"credHelpers":{"repo.example.com":"telesphorepo"}}' > "$DOCKER_CONFIG/config.json" docker push "repo.example.com/docker-hosted-rehearsal/app:$GITHUB_SHA" env: TELESPHOREPO_SERVER: "https://repo.example.com" Jenkins: the build stage runs docker build with the tag ${GIT_COMMIT:-$BUILD_NUMBER}. A publish stage after it runs, inside withEnv(['TELESPHOREPO_SERVER=https://repo.example.com']) and withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]): curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" and then the three lines of the GitHub publish step, with ${GIT_COMMIT:-$BUILD_NUMBER} as the tag. CI for a Helm chart installs Helm (for example azure/setup-helm@v4), then the CLI, and runs telesphorepo publish. With its identity token, a job reads only what anyone can read, so to build from a private base image, log in with the read token before the build. ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com.13. Publish from this computer: run telesphorepo status and check the credential helper entry, then docker push repo.example.com/docker-hosted-rehearsal/<image>:<tag>. For a chart, run telesphorepo publish in its folder. If the server says my account may not publish, ask me for Publish on docker-hosted-rehearsal.14. Verify: remove the local image, then docker pull repo.example.com/docker-hosted-rehearsal/<image>:<tag>. For a chart, run helm pull oci://repo.example.com/docker-hosted-rehearsal/<chart> --version <version> in a new temporary folder, then delete the folder.15. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: point the image names and the repo of telesphorepo.toml at docker-hosted, check that the CI pipeline lists docker-hosted, publish once, then delete docker-hosted-rehearsal.Debian or raw files: download addresses only
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- apt-hosted -> apt-hosted- raw-files -> raw-filesPrivate repositories (they need a read token): none
Scope: the download addresses only. Publishing stays on Nexus: leave the publish addresses,credentials and steps as they are.
Do this:1. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in apt sources (/etc/apt/sources.list.d/*.list and *.sources, and the Dockerfiles, Ansible, cloud-init files or scripts that write them), keyrings and signed-by, curl or wget of Nexus files, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. For each Nexus repository not in my list, ask me its name and wait.2. Change every download address. apt: deb https://nexus.example.com/repository/<nexus name>/ <dist> main becomes deb [signed-by=/etc/apt/keyrings/<name>.asc] https://repo.example.com/debian/<name> <dist> main. The copy keeps the distribution of the Nexus repository and puts every package in the component main. Ask me which signing key the repository got: with the Nexus key, the machines keep their trust; with another key, they install it from https://repo.example.com/debian/<name>/key.asc into /etc/apt/keyrings/<name>.asc. Raw: https://nexus.example.com/repository/<nexus name>/<path> becomes https://repo.example.com/raw/<name>/<path>; the files keep their paths.3. Checksums: keep every sha256sum or checksum check of a downloaded file as it is.4. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. curl gets the credentials on stdin, never as an argument: printf 'user = "%s:%s"\n' "$TELESPHOREPO_READ_USER" "$TELESPHOREPO_READ_TOKEN" | curl -fsSL -K - -o <file> <address> apt reads credentials only from /etc/apt/auth.conf.d/. Give me these lines to run; they read the token at a hidden prompt: printf 'Read token: '; read -rs READ_TOKEN; echo sudo install -m 600 /dev/null /etc/apt/auth.conf.d/<name>.conf printf 'machine %s login <user> password %s\n' https://repo.example.com/debian/<name> "$READ_TOKEN" | sudo tee -a /etc/apt/auth.conf.d/<name>.conf > /dev/null5. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Then test the downloads (for apt, apt-get update in a throwaway debian container with the new source and key; for raw files, each download with curl and its checksum), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run it and send you the output.6. Report: each file you changed, each Nexus address left and why, and each place you were unsure about.Debian or raw files: full switch-over with publishing
Move this project from our Nexus server to Telesphorepo with me. Do every step you can. Foreach step marked ME, tell me exactly what to do, then wait until I say it is done. Never put apassword or a token in a file, a command line or this chat: read each secret from anenvironment variable or a CI secret. Ask me before you change a file outside the project. Keepevery checksum and hash: Telesphorepo holds the same bytes as Nexus.
Telesphorepo: https://repo.example.comNexus: https://nexus.example.comRepositories (Nexus name -> Telesphorepo name):- apt-hosted -> apt-hosted- raw-files -> raw-filesPrivate repositories (they need a read token): none
Scope: the full switch-over. First the download addresses, then publishing with theTelesphorepo CLI. The copies refuse uploads until the switch-over, so we rehearse on a testrepository, apt-hosted-rehearsal, and move to apt-hosted after the switch-over.
Do this:1. ME, first: ask me for the test repository and the CI pipeline, so I make them while you work. I make a hosted Debian or Raw repository named apt-hosted-rehearsal (Repositories page, New repository), where my account has Publish. A server admin adds the CI pipeline of this project (Settings › People and CI › CI pipelines) with the repositories apt-hosted-rehearsal and apt-hosted. Tell me the values for it: for GitHub Actions, the GitHub repository, the workflow file and the branch; for Jenkins, the Jenkins address and the full job name.2. Find every place that names Nexus. Search every file, hidden folders too, for the Nexus host and for /repository/. Look in apt sources (/etc/apt/sources.list.d/*.list and *.sources, and the Dockerfiles, Ansible, cloud-init files or scripts that write them), keyrings and signed-by, curl or wget of Nexus files, and in CI files (.github/workflows, Jenkinsfile, .gitlab-ci.yml and others), Dockerfiles, compose files, scripts and READMEs. Note how the project publishes to Nexus today. For each Nexus repository not in my list, ask me its name and wait.3. Change every download address. apt: deb https://nexus.example.com/repository/<nexus name>/ <dist> main becomes deb [signed-by=/etc/apt/keyrings/<name>.asc] https://repo.example.com/debian/<name> <dist> main. The copy keeps the distribution of the Nexus repository and puts every package in the component main. Ask me which signing key the repository got: with the Nexus key, the machines keep their trust; with another key, they install it from https://repo.example.com/debian/<name>/key.asc into /etc/apt/keyrings/<name>.asc. Raw: https://nexus.example.com/repository/<nexus name>/<path> becomes https://repo.example.com/raw/<name>/<path>; the files keep their paths.4. Checksums: keep every sha256sum or checksum check of a downloaded file as it is.5. Private repositories, only if my list names one. ME: I make a read token (Settings › Tokens, New read token, Create token) and set it, with my username, in TELESPHOREPO_READ_USER and TELESPHOREPO_READ_TOKEN, here and as CI secrets. Tell me these names first, and never ask me for the token. Never use the name TELESPHOREPO_TOKEN: the CLI sets it when it publishes. Wire the variables in. curl gets the credentials on stdin, never as an argument: printf 'user = "%s:%s"\n' "$TELESPHOREPO_READ_USER" "$TELESPHOREPO_READ_TOKEN" | curl -fsSL -K - -o <file> <address> apt reads credentials only from /etc/apt/auth.conf.d/. Give me these lines to run; they read the token at a hidden prompt: printf 'Read token: '; read -rs READ_TOKEN; echo sudo install -m 600 /dev/null /etc/apt/auth.conf.d/<name>.conf printf 'machine %s login <user> password %s\n' https://repo.example.com/debian/<name> "$READ_TOKEN" | sudo tee -a /etc/apt/auth.conf.d/<name>.conf > /dev/null6. Check: search again for the Nexus host and /repository/, and explain each hit that is left. Then test the downloads (for apt, apt-get update in a throwaway debian container with the new source and key; for raw files, each download with curl and its checksum), and check that every download comes from repo.example.com. If your shell lacks the token variables, ask me to run it and send you the output.7. If telesphorepo version fails, install the CLI: curl -fsSL https://repo.example.com/install.sh | sh (Linux and macOS) irm https://repo.example.com/install.ps1 | iex (Windows PowerShell) It goes into ~/.local/bin (Windows: %LOCALAPPDATA%\Programs\telesphorepo). Use the full path if that folder is not on your PATH yet.8. Approve this computer: run telesphorepo login https://repo.example.com. It prints a link and a code, then waits. If your shell shows output only when a command ends, run it in the background and read its output. ME: give me the link and the code. I open the link, sign in, check the code, click Approve device and confirm with my second step. Wait until the CLI prints "This computer is device". This computer can then publish wherever my account has Publish.9. Remove the Nexus publishing: the curl -u uploads to Nexus and their passwords. telesphorepo publish <file> uploads files: for raw into the folder path of telesphorepo.toml, for Debian each .deb into dist and component. List the CI secrets nothing uses now.10. Write telesphorepo.toml next to the build script. It holds no secret, and the project commits it: server = "https://repo.example.com" repo = "apt-hosted-rehearsal" For a raw repository, add path = "<folder in the repository>". For a Debian repository, add dist = "<distribution>" and component = "main".11. CI. GitHub Actions: the publish job gets permissions: id-token: write (keep contents: read), then actions/checkout@v7, the build step that makes the files, then - run: curl -fsSL https://repo.example.com/install.sh | sh - run: telesphorepo publish <files> Jenkins: keep the build stage (the build that makes the files), and add a publish stage after it. Only that stage gets the identity token, which lasts 10 minutes. Inside withCredentials([string(credentialsId: 'telesphorepo-id-token', variable: 'OIDC_TOKEN')]) it runs, on a Unix agent: curl -fsSL https://repo.example.com/install.sh | sh export PATH="$HOME/.local/bin:$PATH" telesphorepo publish <files> and on a Windows agent, in powershell: & ([scriptblock]::Create((irm https://repo.example.com/install.ps1))) telesphorepo publish <files> ME: Jenkins needs the plugin OpenID Connect Provider, and a credential of the kind "OpenID Connect id token" with the ID telesphorepo-id-token and the audience https://repo.example.com. A CI job that downloads from a private repository gets the read token variables from secrets.12. Publish from this computer: run telesphorepo status and check the command it names, then run telesphorepo publish with the files, for example telesphorepo publish build/hello_1.0_amd64.deb. If the server says my account may not publish, ask me for Publish on apt-hosted-rehearsal.13. Verify: for raw, download the file with curl and compare its SHA-256. For Debian, in a throwaway debian container, add the source and key of apt-hosted-rehearsal, then run apt-get update and apt-get install <package>.14. Report: each file you changed, each Nexus address left and why, each place you were unsure about, the CI secrets nothing uses now, and this note for the switch-over day: set repo in telesphorepo.toml to apt-hosted, check that the CI pipeline lists apt-hosted, publish once, then delete apt-hosted-rehearsal.The steps that need you
Section titled “The steps that need you”The agent asks for each step when it needs it. It waits until you say it is done.
- Approve the computer. Open the link that the agent gives you, and sign in. Check the code, click Approve device, and confirm with your second step.
- Make a read token, only for a private repository. Open Settings › Tokens, click New read token, type a name, and click Create token. Put it in the variables that the agent names. Never paste it to the agent.
- Make the test repository, for the full switch-over. Open the Repositories page, and click New repository. Make a hosted repository where your account has Publish.
- Add the CI pipeline, for the full switch-over. A server admin adds it on Settings › People and CI › CI pipelines, with the values that the agent gives you. For Jenkins, see also Set up Jenkins.
After the switch-over
Section titled “After the switch-over”When your admin has switched over, follow the note in the agent’s report:
-
Set
repointelesphorepo.tomlto the real repository. -
Check that the CI pipeline lists the real repository.
-
Publish once.
-
Delete the test repository.
Use the skill
Section titled “Use the skill”With Claude Code, you can use the skill telesphorepo-migrate instead of a prompt. It asks you for the addresses and names, and finds the ecosystems in the project by itself.
-
Copy the skill into
~/.claude/skills/, or into.claude/skills/of one project. On Windows, the user folder is%USERPROFILE%\.claude\skills\.Terminal window git clone --depth 1 https://github.com/Telesphorepo/Telesphorepo.git /tmp/telesphorepomkdir -p ~/.claude/skillscp -r /tmp/telesphorepo/skills/telesphorepo-migrate ~/.claude/skills/ -
Open Claude Code in the project folder, and ask:
Move this project from Nexus to Telesphorepo.