feat: add migrate urls command#38
Merged
Merged
Conversation
Add a `migrate` command group with a `urls` subcommand that translates old twist.com URLs to their Comms equivalents via Twist's `comms_migration/fetch_new_url` endpoint, wrapped by the SDK helpers `fetchNewCommsUrls`/`fetchNewCommsUrl` (comms-sdk-typescript#42). The endpoint authenticates with a Twist (not Comms) token, so the command reads it from a `--twist-token` flag or the `TWIST_AUTH_TOKEN` environment variable (the flag wins) and never touches the Comms auth path. The skill recommends supplying it via the Twist CLI: `--twist-token "$(tw auth token view)"`. URLs come from a comma-separated argument or stdin. Output is one line per URL (`old -> new`, or `old ✗ <code>` on failure); `--json`/`--ndjson` give structured results. Per-URL failures don't abort the run, and the command exits non-zero if any URL fails to migrate. Bumps @doist/comms-sdk 0.4.6 -> 0.7.0 for the migration helpers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ed3c6f2 to
c37cceb
Compare
doistbot
reviewed
Jun 26, 2026
doistbot
left a comment
Member
There was a problem hiding this comment.
This PR adds a tdc migrate urls command that translates Twist URLs to their Comms equivalents via the new SDK migration helpers, with Twist-token auth, stdin/argument input, and text/JSON/NDJSON output.
Few things worth tightening:
- Missing spinner: The
fetchNewCommsUrlscall bypasses the shared client's spinner middleware, so wrap it explicitly withwithSpinnerfrom../../lib/spinner.jsto give users progress feedback as required by the repo guidelines. - Stdin can hang: When
[urls]is omitted the command unconditionally waits onreadStdinToEnd(), which blocks until EOF and can hang in non-interactive/CI environments with an open but empty stdin. Adopt the same "wait for first byte, then read to end" pattern used elsewhere before committing to a full read. - Error code stability: The fallback that sets
error.codetoerror.messageturns unexpected failures into arbitrary prose and forces message-text matching. Use a stable machine-readable code (e.g.API_ERROR/UNKNOWN_ERROR) and keep the human-readable text inmessage. - Secret handling & discoverability:
--twist-tokenexposes the token in process listings, which conflicts with the Doist secrets-management standard; consider makingTWIST_AUTH_TOKENthe documented primary method and de-emphasizing the flag. Also addtdc migrateto the skill's top-level quick-reference list so agents discover it, and add test coverage for the--ndjsonoutput path andTWIST_BASE_URLforwarding branch—both are easily reachable with the existing harness.
I also included a few optional follow-up notes in the details below.
Optional follow-up notes (2)
src/lib/skills/content.ts:349: This adds a new top-level command, but the skill’s setup/quick-reference block above still doesn’t mention
tdc migrate.SKILL_CONTENTis the source of truth for installed agent skills, so agents that rely on that top command list won’t discover the new entry. Please addtdc migratethere as well.src/commands/migrate/migrate.test.ts:138: The
--ndjsonoutput path is untested. The production code branches toformatNdjson(output)when--ndjsonis passed (distinct from--json), and other commands in the codebase (e.g.groups.test.ts) include NDJSON integration assertions. Adding a test with--ndjson— verifying the output parses as newline-delimited JSON with the expected{ oldUrl, newUrl }/{ oldUrl, error }shapes — would close this gap using the existing harness (samecreateProgram+captureConsolepattern as the--jsontest).
- Wrap the fetchNewCommsUrls call in withSpinner for progress feedback - Read stdin via readStdin (wait-for-first-byte) so an open but empty stdin raises MISSING_CONTENT instead of hanging in CI/spawned children - Use a stable API_ERROR code when the endpoint returns no error code, keeping the human-readable text in message - Iterate results directly for text output; only materialise the simplified shape in the --json/--ndjson branches - Make TWIST_AUTH_TOKEN the documented primary token method and de-emphasise the --twist-token flag (a CLI flag exposes the token in process listings), per the Doist secrets-management standard; the flag still works and overrides the env var - Add tdc migrate urls to the skill's top-level quick-reference list - Add test coverage for --ndjson output, TWIST_BASE_URL forwarding, and the API_ERROR fallback Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
doist-release-bot Bot
added a commit
that referenced
this pull request
Jun 26, 2026
## [1.9.0](v1.8.0...v1.9.0) (2026-06-26) ### Features * add migrate urls command ([#38](#38)) ([99697c0](99697c0))
Contributor
|
🎉 This PR is included in version 1.9.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
As part of the Twist→Comms migration, Twist's backend exposes
POST https://twist.com/api/comms_migration/fetch_new_url, which maps an oldtwist.comURL to its equivalent Comms URL (useful for rewriting bookmarks/history). The Comms SDK was updated to wrap this endpoint in comms-sdk-typescript#42, adding the standalone helpersfetchNewCommsUrl/fetchNewCommsUrls.This PR adds a
tdc migrate urlscommand on top of those helpers.Changes
migratecommand group with aurlssubcommand (src/commands/migrate/). Translatestwist.comURLs to their Comms equivalents.--twist-tokenflag or theTWIST_AUTH_TOKENenvironment variable (the flag wins) and never touches the Comms auth path. The recommended way to supply it is via the Twist CLI, if installed:--twist-token "$(tw auth token view)".old -> newon success,old ✗ <code>on failure (invalid_url/not_imported).--json/--ndjsongive structured{ oldUrl, newUrl }/{ oldUrl, error }results. Per-URL failures don't abort the run; the command exits non-zero if any URL fails to migrate.@doist/comms-sdk0.4.6 → 0.7.0 (first published version carrying the migration helpers). Type-check is clean across the bump.src/lib/skills/content.ts) gains a## Migrationsection documenting the command and the Twist-CLI token pattern;SKILL.mdregenerated.CODEBASE.mdmap/catalog updated.Verification
npm run type-check,npm run lint:check,npm run check:skill-sync— all clean.npm test— 808 passed, including 7 new tests insrc/commands/migrate/migrate.test.ts.✗ invalid_url;--jsonand stdin paths confirmed.🤖 Generated with Claude Code