Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
dc29b6b
Reload the application once so first-run breakpoints are hit (#1)
teoboetti Sep 28, 2026
7a27b7b
React Native 0.87 debugger fixes and local build tooling (#2)
teoboetti Sep 28, 2026
170ec37
Document installing in VSCodium, and mark local builds as patched (#3)
teoboetti Sep 28, 2026
280825d
Merge upstream 1.14.x into the patched fork
teoboetti Sep 29, 2026
408af82
Fix localized strings, Android launch errors and stop Metro on debug …
teoboetti Oct 6, 2026
8bb875c
chore: add project Claude Code settings to disable commit attribution…
teoboetti Oct 6, 2026
d55594f
chore(lint): clear all eslint warnings (#6)
teoboetti Oct 6, 2026
37e8738
chore: release 1.14.20261006
teoboetti Oct 6, 2026
b4b8282
chore(ci): add weekly upstream sync workflow (#7)
teoboetti Oct 6, 2026
9274535
Merge branch 'master' of https://github.com/microsoft/vscode-react-na…
Oct 12, 2026
2d6d1df
Merge pull request #8 from teoboetti/upstream-sync
teoboetti Oct 12, 2026
dfcd2e4
chore: release 1.14.20261012
teoboetti Oct 12, 2026
be0ba9b
chore: add release skill for cutting and installing patched builds
teoboetti Oct 12, 2026
5d5a2de
Merge branch 'master' of https://github.com/microsoft/vscode-react-na…
Oct 12, 2026
35408e5
Merge pull request #9 from teoboetti/upstream-sync
teoboetti Oct 13, 2026
efaee8a
Merge branch 'master' of https://github.com/microsoft/vscode-react-na…
Oct 19, 2026
89452f4
fix: resolve lint warnings in reactNativeSessionManager
teoboetti Oct 19, 2026
78a23da
Merge pull request #10 from teoboetti/upstream-sync
teoboetti Oct 19, 2026
21bb394
chore: release 1.14.20261019
teoboetti Oct 19, 2026
0c816de
feat: add Flutter-style device selector
teoboetti Oct 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"attribution": {
"commit": "",
"pr": "",
"sessionUrl": false
}
}
84 changes: 84 additions & 0 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: release
description: Use when asked to deploy, release, publish, cut or tag a new version of this patched vscode-react-native fork (versions like v1.14.20261012), or to install the latest patched VSIX into the local editor.
argument-hint: "[version] [install] | install"
---

# Release the patched fork

## Mode

Decide the mode from the request:
- **Install only.** The request asks to install and doesn't mention deploy/release/publish. Set `V=$(gh release view --repo teoboetti/vscode-react-native --json tagName -q .tagName | sed 's/^v//')`, then do step 5 only.
- **Release.** Do steps 1-4. Also do step 5 if the request mentions install.
- **Version.** If the request names one (e.g. `1.14.20261020`), use it without the `v`. Otherwise use `<major>.<minor>.$(date +%Y%m%d)`, taking major.minor from `package.json`. If that version is already released, STOP and ask. Never add a suffix to the date: `1.14.2026101201` sorts above every later date and blocks future releases.

## How this works

A release is a `chore: release X` commit that bumps the version in `package.json` and `package-lock.json`, plus a `vX` tag **on that commit**. Pushing the tag runs `.github/workflows/build-vsix.yml`, which builds the VSIX and creates the GitHub release with it attached. The VSIX version comes from `package.json`, not from the tag.

**Shell variables don't persist between Bash calls.** Start every call with:
```bash
cd "$(git rev-parse --show-toplevel)"; R=teoboetti/vscode-react-native; V=<version>
```
Pass `--repo $R` to every `gh` call. The gh default repo here is upstream `microsoft/vscode-react-native`.

## Steps

**1. Preflight.** If any check fails, STOP and report it:
```bash
git fetch origin --quiet
git status --porcelain --untracked-files=no # must print nothing
git rev-parse --abbrev-ref HEAD # must be master
git rev-parse master origin/master # both lines must match
gh run list --repo $R --workflow ci.yml --commit "$(git rev-parse HEAD)" --limit 1 # must be completed + success
node -p 'require("./package.json").version' # must be lower than $V
```

**2. Tag check.**
```bash
git ls-remote --tags origin "v$V" # prints anything → already released: STOP and report
git tag -l "v$V" # prints the tag → it's a stale local tag: git tag -d "v$V"
```

**3. Bump, commit, tag.**
```bash
OLD=$(node -p 'require("./package.json").version')
sed -i '' "s/\"version\": \"$OLD\"/\"version\": \"$V\"/" package.json package-lock.json
grep -c "\"version\": \"$V\"" package.json package-lock.json # must be package.json:1, package-lock.json:2
git commit -am "chore: release $V" # a pre-commit lint hook runs
git tag "v$V"
```
The commit gets no attribution trailers. If anything in steps 3-4 fails **before the push**, undo it with `git tag -d "v$V"; git reset --hard origin/master`, then STOP and report. This is safe because preflight confirmed there were no tracked changes.

**4. Push and verify.** Use a 10-minute Bash timeout.
```bash
git push --atomic origin master "v$V" # both refs land, or neither does
for i in $(seq 12); do id=$(gh run list --repo $R --workflow build-vsix.yml --branch "v$V" --commit "$(git rev-parse HEAD)" --limit 1 --json databaseId -q '.[0].databaseId'); [ -n "$id" ] && break; sleep 5; done
gh run watch "${id:?no build-vsix run found for v$V}" --repo $R --exit-status --interval 15
gh release view "v$V" --repo $R --json url,assets -q '.url, .assets[].name' # must list vscode-react-native-$V.vsix
```
If the build fails after the push, don't delete the pushed tag. Report the run URL; rerunning it is the user's call.

**5. Install.** The patched build lives in **VSCodium** (`codium`). VS Code (`code`) runs the Microsoft marketplace version, so don't touch it unless the request names it (then use `code` wherever this step says `codium`).
```bash
codium --list-extensions --show-versions | grep -x "msjsdiag.vscode-react-native@$V" # prints → already installed: skip the next two commands
D=$(mktemp -d) && gh release download "v$V" --repo $R --dir "$D" && codium --install-extension "$D/vscode-react-native-$V.vsix" --force
codium --list-extensions --show-versions | grep -x "msjsdiag.vscode-react-native@$V" # must print
```

## Report

Report in a few lines. On success, give the version, the commit sha, the release URL, the VSIX asset name, and the installed version if you installed. After an install, remind the user to run **Developer: Reload Window** in VSCodium. On a STOP, give the failing command, its output, and anything you undid.

## Common mistakes

| Mistake | Result |
|---|---|
| Tagging before bumping `package.json` | VSIX and release carry the previous version |
| Bumping only `package.json` | `npm ci` in the workflow fails on the lockfile mismatch |
| Using `npm version` to bump | Can rewrite the v2 lockfile |
| Bare `gh` without `--repo $R` | Queries the upstream Microsoft repo |
| Picking the build run without `--branch` + `--commit` | Can watch an old run from an earlier push of the same tag |
| Pushing `master` and the tag separately | One can land without the other, and the undo step then deletes the only copy of the tag |
| Installing a local `npx vsce package` build | Installed build differs from the published release |
32 changes: 31 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,37 @@ module.exports = {
cases: {
camelCase: true, // pascalCase: true,
},
ignore: [/rn-extension\.ts/],
ignore: [
/rn-extension\.ts/,
/CDPAPINames\.ts/,
/ConsoleLogger\.ts/,
/ICDPMessageHandler\.ts/,
/IExperiment\.ts/,
/IWDPHelper\.ts/,
/LogHelper\.ts/,
/NullLogger\.ts/,
/OutputChannelLogger\.ts/,
/RNTPreviewPrompt\.ts/,
/baseCDPMessageHandler\.ts/,
/configEASBuild\.ts/,
/graphQLFormatter\.ts/,
/hermesCDPMessageHandler\.ts/,
/iOSClienDevice\.ts/,
/iOSContainerUtility\.ts/,
/iOSDebugModeManager\.ts/,
/iOSDeviceTracker\.ts/,
/iOSDirectCDPMessageHandler\.ts/,
/iOSPlatform\.ts/,
/iOSTargetManager\.ts/,
/macOSDebugModeManager\.ts/,
/macOSPlatform\.ts/,
/nodeJS\.ts/,
/openEASProject\.ts/,
/openRNUpgradeHelper\.ts/,
/reactNativeCDPProxy\.ts/,
/reopenQRCode\.ts/,
/rnCDPMessageHandler\.ts/,
],
},
],
"unicorn/no-array-reduce": "warn",
Expand Down
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
51 changes: 51 additions & 0 deletions .github/workflows/build-vsix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Build VSIX

# Packages the extension and, for a v* tag, attaches the VSIX to that release
# so it can be installed on a machine without the build toolchain:
#
# gh release download v1.14.2 --repo teoboetti/vscode-react-native
# codium --install-extension vscode-react-native-1.14.2.vsix

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write

jobs:
package:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v7
with:
node-version: "24"
cache: npm

- name: Install dependencies
run: npm ci

- name: Package
run: npx vsce package

- name: Attach the VSIX to the release
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
gh release upload "$GITHUB_REF_NAME" ./*.vsix --clobber
else
gh release create "$GITHUB_REF_NAME" ./*.vsix --generate-notes
fi

- uses: actions/upload-artifact@v7
with:
name: vsix
path: "*.vsix"
if-no-files-found: error
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI

on:
push:
branches:
- master
pull_request:

permissions:
contents: read

jobs:
ci:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v7
with:
node-version: "24"
cache: npm

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Bundle extension
run: npx gulp prod-build

- name: Build
run: npm run build

- name: Test
run: xvfb-run -a npm test

- name: Localization tests
run: xvfb-run -a npm run test-localization
66 changes: 66 additions & 0 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Sync upstream

on:
schedule:
- cron: "0 6 * * 1" # Mondays 06:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
sync:
runs-on: ubuntu-latest
env:
# PAT (repo + workflow scopes): GITHUB_TOKEN can't push upstream workflow changes and its PRs don't trigger CI
GH_TOKEN: ${{ secrets.SYNC_PAT }}

steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
token: ${{ secrets.SYNC_PAT }}

- uses: actions/setup-node@v7
with:
node-version: "24"
cache: npm

- name: Merge upstream
id: merge
run: |
# an open sync PR may hold manual fixes; don't overwrite it
gh pr list --head upstream-sync --state open --json number -q '.[].number' | grep -q . && exit 0
git config user.name "upstream-sync"
git config user.email "upstream-sync@users.noreply.github.com"
git fetch https://github.com/microsoft/vscode-react-native.git master
[ "$(git rev-list --count HEAD..FETCH_HEAD)" = 0 ] && exit 0
git checkout -b upstream-sync
if git merge --no-edit FETCH_HEAD; then
echo "result=clean" >> "$GITHUB_OUTPUT"
else
echo "files=$(git diff --name-only --diff-filter=U | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
echo "result=conflict" >> "$GITHUB_OUTPUT"
fi

- name: Resolve conflicts with Claude
if: steps.merge.outputs.result == 'conflict'
timeout-minutes: 30 # hard cap; the default is 6 hours
run: npx -y @anthropic-ai/claude-code -p "$PROMPT" --allowedTools "Bash,Read,Edit,Write" --max-turns 40 --model sonnet
env:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} # from `claude setup-token`
PROMPT: |
A merge of microsoft/vscode-react-native master into this fork stopped on conflicts in:
${{ steps.merge.outputs.files }}
Resolve them: take upstream's changes but keep this fork's patches (see `git log` for fork-only commits).
Then run `npm ci`, `npm run lint`, `npx gulp prod-build` and `npm run build`, and fix anything the merge broke.
Finish with `git add -A` and `git commit --no-edit`. Do not push.

- name: Open PR
if: steps.merge.outputs.result != ''
run: |
if git grep -n '^<<<<<<< '; then exit 1; fi # leftover conflict markers: fail, no PR
git push -f origin upstream-sync
gh pr create --head upstream-sync --base master \
--title "Sync upstream $(date +%F)" \
--body "Weekly upstream merge. Files resolved by Claude: ${{ steps.merge.outputs.files || 'none' }}"
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,49 @@ You can not only download React Native Tools in the marketplace, but can also pa

Building and testing React Native Tools from source requires Node.js 22 or later. This development requirement does not affect the runtime requirements of the installed extension.

## Install in VSCodium

VSCodium installs extensions from [Open VSX](https://open-vsx.org/), which does not carry this fork, so install the packaged `.vsix` directly.

### From a release

A `v*` tag builds the extension in CI and attaches the `.vsix` to the release, so no local toolchain is needed:

```bash
gh release download --repo teoboetti/vscode-react-native --pattern '*.vsix'
codium --install-extension vscode-react-native-*.vsix
```

Omitting the tag takes the latest release; pass one (for example `v1.14.20260928`) to install a specific build.

### From source

```bash
git clone https://github.com/teoboetti/vscode-react-native.git
cd vscode-react-native
npm install
npm run install-local
```

`npm run install-local` stamps the version with the build date, packages the extension and installs it into VSCodium in one step.

Reload the window afterwards (**Developer: Reload Window**) for VSCodium to pick up the new build.

If `codium` is not on your `PATH`, run **Shell Command: Install 'codium' command in PATH** from the Command Palette, or install the `.vsix` through **Extensions: Install from VSIX...**.

### Telling it apart from the published extension

Local builds are named **React Native Tools (patched)** and versioned `1.14.<YYYYMMDD>`, so they are recognisable in the extensions list and always sort above a published `1.14.x`.

They keep upstream's `msjsdiag.vscode-react-native` identifier, so VSCodium may still try to replace one with a marketplace build. Right-click the extension and choose **Disable Auto Update** to prevent that.

To pick up upstream changes and rebuild:

```bash
git fetch upstream && git rebase upstream/master
npm run install-local
```

## About the extension

This VS Code extension provides a development environment for React Native and Expo projects.
Expand All @@ -34,6 +77,7 @@ Using this extension, you can **debug your code and quickly run `react-native` o

- [React Native Tools Preview](#react-native-tools-preview)
- [Package extension locally](#package-extension-locally)
- [Install in VSCodium](#install-in-vscodium)
- [About the extension](#about-the-extension)
- [Getting started](#getting-started)
- [React Native commands in the Command Palette](#react-native-commands-in-the-command-palette)
Expand Down
4 changes: 2 additions & 2 deletions gulp_scripts/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const generateSrcLocBundle = () => {
return runTypeScriptCompile().then(() =>
streamToPromise(
gulp
.src(["src/**/*.js"], { base: ".", allowEmpty: true })
.src(["src/**/*.js"], { base: appRoot, allowEmpty: true })
.pipe(nls.createMetaDataFiles())
.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, "i18n"))
.pipe(nls.bundleMetaDataFiles(fullExtensionName, "dist"))
Expand Down Expand Up @@ -81,7 +81,7 @@ async function build(failOnError, buildNls) {
await runTypeScriptCompile();

const stream = gulp
.src(["src/**/*.js", "test/**/*.js"], { base: ".", allowEmpty: true })
.src(["src/**/*.js", "test/**/*.js"], { base: appRoot, allowEmpty: true })
.pipe(createLinePreservingPreprocessor(preprocessorContext))
.pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through())
.pipe(
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading