A VS Code extension that brings NetSuite developer tools into the editor. Provides an Entity Designer, Records Catalog browser, Script Logs viewer, SuiteQL Query Editor, Environment Compare, a Performance Tracker, and Copilot/Claude integration — all backed by OAuth2 M2M authentication.
Features
| Tool |
Status |
Description |
| Entity Designer |
Stable |
Generate defineEntity(...) configs and TypeScript interfaces from live NetSuite metadata |
| Records Catalog |
Stable |
Browse tables, fields, joins, subrecords, and sublists from the sidebar |
| Script Logs |
Stable |
View execution logs with filtering by script, user, date range, and level; AI analysis panel |
| Query Editor |
Stable |
Write and run SuiteQL with syntax highlighting, autocompletion, saved queries, and query history |
| Environment Compare |
Stable |
Diff SDF objects and FileCabinet files between environments (or local ↔ environment) scoped to your workspace |
| Performance Tracker |
Stable |
View SuiteScript execution performance data — runs, call trees, and timing breakdowns — inside VS Code, plus workspace helpers for adopting tracker instrumentation |
| Copilot / Claude Tools |
Stable |
Language model tools that let Copilot Chat or Claude Code query script logs, list scripts and users, and inspect open panels |
| Setup & Maintenance |
Stable |
Setup wizard, OAuth profile management, diagnostics, and metadata bridge install/uninstall |
Companion npm Packages
The extension is the authoring and tooling surface. The code it generates and the instrumentation it visualizes is powered by two runtime libraries published to npm. Install whichever you need in the SuiteScript project you are working on.
| Package |
Used by |
What it provides |
@amerilux/netsuite-repository |
Entity Designer |
The defineEntity(...) runtime that backs the configs the Designer generates — repository pattern over N/record, N/search, and SuiteQL with typed field access |
@amerilux/netsuite-wrapper |
Performance Tracker |
The wrapper/instrumentation library that emits the execution data the Tracker panel reads — wrap entry points and helper functions to get timing, call trees, and run history |
npm install @amerilux/netsuite-repository # for Entity Designer output
npm install @amerilux/netsuite-wrapper # for Performance Tracker instrumentation
The other features (Records Catalog, Script Logs, Query Editor, Environment Compare, Setup) do not require any runtime package — they work against a stock NetSuite account.
Setup Guide
The extension connects to NetSuite via OAuth 2.0 Machine-to-Machine (M2M) client credentials. You will complete four phases:
- NetSuite account configuration
- Generate a certificate and private key
- Configure the VS Code extension
- Install the Metadata Bridge (optional)
1a. Enable required features
In NetSuite, go to Setup > Company > Enable Features > SuiteCloud tab and enable:
- SuiteCloud Development Framework — required for metadata bridge deployment
- Server SuiteScript — required for Suitelet and RESTlet scripts
- REST Web Services — required for OAuth token endpoint and REST metadata calls
Save changes.
1b. Create an Integration record
Go to Setup > Integration > Manage Integrations > New.
| Field |
Value |
| Name |
VS Code NetSuite Repository (or any name you like) |
| State |
Enabled |
| OAuth 2.0 |
Check Client Credentials (Machine to Machine) |
| Scope |
Check REST Web Services and RESTlets |
Save the record. Note the Client ID shown on the saved record — you will need it when configuring the extension connection profile.
Do not use the Client Secret. The extension uses certificate-based M2M, not secret-based.
1c. Upload your certificate and create the credential mapping
After generating a certificate (see step 2), return to NetSuite and go to Setup > Users/Roles > OAuth 2.0 Client Credentials (M2M) Setup > New.
| Field |
Value |
| Entity |
The NetSuite user account the token should run as |
| Role |
The role to apply when the token is exchanged (must have REST Web Services and RESTlets permissions) |
| Application (Integration) |
Select the integration record created in step 1b |
| Certificate |
Upload the netsuite-cert.pem file you generated |
Save the record. Note the Certificate ID shown on the saved record.
2. Generate a Certificate and Private Key
Run the following commands on your local machine. The private key stays on your machine — only the certificate is uploaded to NetSuite.
openssl genrsa -out netsuite-private.pem 2048
openssl req -new -x509 -key netsuite-private.pem -out netsuite-cert.pem -days 730
Store netsuite-private.pem in a stable location such as C:/Users/you/.netsuite/netsuite-private.pem. The extension stores the path to this file, not the file contents.
Upload netsuite-cert.pem to NetSuite as described in step 1c.
3a. Open the Setup Wizard
Open the VS Code Command Palette (Ctrl+Shift+P) and run NetSuite Repository: Setup Wizard. The wizard walks through:
- Adding an extension connection profile
- Testing the NetSuite token endpoint
- Installing the Power Tool scripts (the metadata bridge Suitelet and supporting RESTlets)
3b. Connection profile fields
When prompted to add a profile, enter the following:
| Field |
Where to find it |
| Account ID |
Your NetSuite account ID, e.g. 1234567 or 1234567_SB1. Hyphens and underscores are both accepted. |
| OAuth2 Client ID |
From the Integration record saved in step 1b |
| Certificate ID |
From the credential mapping record saved in step 1c |
| Private Key Path |
Absolute path to netsuite-private.pem on your machine |
| OAuth Scopes |
rest_webservices restlet (space-separated) |
| SuiteCloud Auth ID |
From suitecloud account:setup; only needed for metadata bridge deployment |
3c. Test the connection
After saving the profile, run NetSuite Repository: Test NetSuite Connection from the Command Palette to confirm the token endpoint and REST metadata access are working.
Each NetSuite environment (production, sandbox, etc.) needs its own OAuth integration record, certificate, and extension connection profile. Use Switch Active Environment to change which profile is active.
We know this is the rough edge of the extension. Asking you to keep a browser tab open is not what anyone wants. We're keeping it for now because the alternative is doing without live schema metadata, which would gut the Entity Designer and Records Catalog. A native replacement is on the roadmap — see Why it exists below for the constraint we're working around and what we're investigating.
The metadata bridge is what lets the extension see your account's live schema — every custom record, every custom field, every join — instead of shipping a frozen snapshot that goes stale the moment you add a field. It is a small SuiteCloud (SDF) project deployed once per NetSuite environment, plus a browser tab that stays open while you work.
Which features need the bridge?
The painful part of the bridge is the browser tab — the SDF install is one-time per environment, but the tab has to stay open while you work. Only the schema-driven tools (Entity Designer, Records Catalog, Query Editor autocompletion) need that tab. Several other features rely on RESTlets that ship as part of the same install but never touch the browser.
| Feature |
Needs install? |
Needs browser tab open? |
Notes |
| Entity Designer |
✅ |
✅ |
Reads custom record types, field metadata, joins, subrecords, and sublists live from the account |
| Records Catalog |
✅ |
✅ |
Same metadata source as the Designer |
| Query Editor — autocompletion |
✅ |
✅ |
Table/column suggestions come from the catalog; without the bridge, autocomplete falls back to text-only |
| Query Editor — run query |
❌ |
❌ |
SuiteQL runs through NetSuite's public REST endpoint using OAuth M2M directly |
| Script Logs |
✅ |
❌ |
Uses the deployed customscript_nsrepo_rl_scriptlogs RESTlet via OAuth M2M — install required, but no browser session |
| "Open in NetSuite" links (Script Logs, Query Editor, Performance Tracker panels) |
✅ |
❌ |
Each panel can open its full React UI inside a NetSuite browser tab via the matching Suitelet — those Suitelets ship in the install but are only invoked when you click the link |
| Performance Tracker (data) |
❌ |
❌ |
Uses the separate customscript_performancetracker_api RESTlet (not part of this install — see Performance Tracker docs) |
| Environment Compare |
❌ |
❌ |
Uses SuiteCloud CLI (SDF) directly — no bridge involvement |
| Setup / Diagnostics |
❌ |
❌ |
Pure OAuth M2M token + REST calls |
If you only need Query Editor execution, Environment Compare, or pure REST features — you can skip the install entirely. If you want Script Logs, install it once and forget it (no browser tab). The browser tab is only required for the Entity Designer, Records Catalog, and Query Editor autocompletion.
What gets installed
The install is a single SDF project but it deploys several scripts so the rest of the extension has a place to call. Everything lives under SuiteScripts/NetSuiteRepository/ in the File Cabinet and uses the customscript_nsrepo_* prefix in the Script Manager so it is easy to find and uninstall.
Suitelets
| Script ID |
Purpose |
Browser tab required? |
customscript_nsrepo_sl_schema |
The metadata bridge — proxies Records Catalog requests |
✅ Yes (this is the tab you keep open) |
customscript_nsrepo_sl_scriptlogs |
Hosts the full Script Logs React UI inside NetSuite (convenience host for the "Open in NetSuite" link) |
Only when opened |
customscript_nsrepo_sl_queryeditor |
Hosts the full Query Editor React UI inside NetSuite |
Only when opened |
customscript_nsrepo_sl_perftracker |
Hosts the full Performance Tracker React UI inside NetSuite |
Only when opened |
About the three "Open in NetSuite" Suitelets: these are a convenience, not a requirement. The Script Logs, Query Editor, and Performance Tracker panels all work fully inside VS Code — but a VS Code side panel is sometimes too cramped for a wide log table or a busy call tree. Every panel has an Open in NetSuite ↗ link in its toolbar that hands the same UI off to a full-width browser tab, hosted by the matching Suitelet in your own account (no third-party services). If you never click those links, the Suitelets sit idle and cost nothing.
RESTlets
| Script ID |
Purpose |
customscript_nsrepo_rl_scriptlogs |
Data API for the VS Code Script Logs panel |
customscript_nsrepo_rl_storage |
Backing storage for saved queries, run history, and bridge queue state |
File Cabinet assets
The three "Open in NetSuite" Suitelets each ship a small React bundle (index.html + client JS) alongside them in SuiteScripts/NetSuiteRepository/{ScriptLogs,QueryEditor,PerformanceTracker}/.
To remove everything, run NetSuite Repository: Uninstall Metadata Bridge — it deletes the script and deployment records and the File Cabinet folder.
Why it exists
The schema metadata the Entity Designer and Records Catalog rely on comes from NetSuite's Records Catalog endpoint (/app/recordscatalog/rcendpoint.nl). This endpoint is the single source of truth for live, account-specific schema — but it has a constraint we cannot engineer around from outside NetSuite:
- It is an app-session endpoint, not a REST endpoint. It only authenticates against an interactive NetSuite browser session (the same cookie/JWT pair the UI uses). OAuth 2.0 M2M tokens — which work for SuiteQL, RESTlets, and the REST record service — are not accepted here.
- There is no public REST equivalent. NetSuite does not currently expose live Records Catalog metadata through any externally callable API. The SOAP
getCustomizationIds / getList calls return a tiny fraction of what the catalog endpoint returns and miss joins, subrecord shapes, and sublist projections entirely.
- Shipping a frozen snapshot is not a real option. Every NetSuite account is different. Custom records, custom fields, and bundle-installed schema vary per environment, and they change constantly. A bundled snapshot would be wrong on day one for most users.
Given that constraint, the only way to read live schema from outside the NetSuite browser is to borrow an existing browser session. That is what the bridge does:
- A Suitelet (
customscript_nsrepo_sl_schema) is deployed to your account during the one-time install.
- You open it once in a browser tab — that tab now has a valid app session.
- The Suitelet polls a localhost queue served by the VS Code extension.
- When the Designer or Catalog needs schema, the extension drops a request on the queue. The browser tab picks it up, calls
rcendpoint.nl with its own session, and posts the response back.
No data flows to any third party. The queue is 127.0.0.1-only and exists only while VS Code is running. The browser tab is doing exactly what your browser would do if you were clicking through the Records Catalog UI manually — the extension is just driving it.
What we're doing about it
- Tracking NetSuite REST coverage. If Oracle exposes Records Catalog (or a superset) through OAuth M2M, the bridge becomes unnecessary and we will remove it.
- Investigating a headless session approach so the browser tab can be replaced with a background process the extension manages on your behalf.
- Keeping the install scoped. Everything lives under one File Cabinet folder and one
customscript_nsrepo_* prefix so it is trivial to audit and uninstall. We add scripts here when a feature genuinely needs them, not for convenience.
If you have a constraint that makes the bridge unworkable for your team (locked-down browsers, kiosked workstations, etc.), please file an issue — we want to hear it.
Prerequisites
Install the SuiteCloud CLI and sign in to the target NetSuite account:
npm install -g @oracle/suitecloud-cli
suitecloud account:setup
Use a role that can deploy SDF projects and create script and deployment records. The auth ID created by suitecloud account:setup is what you enter as the SuiteCloud Auth ID in the extension connection profile.
Deploy the bridge
- Open the Command Palette and run NetSuite Repository: Install Metadata Bridge.
- Select the environments to deploy to.
- Confirm or enter the SuiteCloud CLI auth ID for each selected environment.
- At the audience prompt, include the NetSuite browser role that has Setup > Records Catalog permission.
- The extension runs
suitecloud project:adddependencies, then project:validate, then project:deploy. Deploy only runs if validation passes.
- After deployment, open the bridge tab from the Open Metadata Bridge Tab button in the sidebar settings panel. Keep this browser tab open while using the Entity Designer or Records Catalog.
Bridge files are written to VS Code global extension storage, not into the workspace.
See docs/metadata-bridge.md for detailed technical information.
Command Groups
Each feature area has its own reference page:
Project Config
The extension does not assume a project structure. Add netsuite-repository.config.json at the workspace root or run NetSuite Repository: Create Project Config.
{
"repositoryDir": "netsuite/src/repositories",
"typesDir": "netsuite/src/repository-types",
"runtimeDir": ".netsuite-repository/runtime",
"manifestPath": ".netsuite-repository/manifest.json"
}
repositoryDir — generated .config.ts files
typesDir — generated .types.ts files
runtimeDir / manifestPath — reserved for the bundled engine/install flow
Settings
| Setting |
Default |
Description |
netsuiteRepositoryPowerTools.designer.debug.enabled |
false |
Show the designer webview debug log and write detailed entries to the output channel |
netsuiteRepositoryPowerTools.browserCompanion.enabled |
false |
Show browser companion status in the Setup Wizard and Settings panel (legacy metadata fallback; the Suitelet bridge is the primary path) |
netsuiteRepositoryPowerTools.scriptLogs.chatTarget |
copilot |
Which AI chat assistant receives logs sent from the Script Logs panel — copilot (@github) or claude (@claude) |
netsuiteRepositoryPowerTools.performanceToolkit.excludePatterns |
[] |
Additional glob patterns to exclude when the Performance Tracker scans the workspace for NetSuite scripts |
Troubleshooting
INVALID_LOGIN errors
Run NetSuite Repository: Diagnose NetSuite Auth. It reports the SuiteCloud CLI auth ID from project.json, the active extension connection profile, token endpoint, scopes, token request status, and REST metadata status.
Certificate or key errors
Confirm that the private key path in your extension connection profile matches the actual file location and that the certificate uploaded to NetSuite matches the key used to sign it. Regenerate and re-upload if the certificate has expired (default validity is 730 days).
Metadata bridge opens in browser
This is expected. The Suitelet bridge opens in your NetSuite browser session to access Records Catalog metadata. Leave the browser tab open while using the Entity Designer or Records Catalog.
Trusted domain prompts
The first time VS Code opens a link to your NetSuite app origin (e.g. https://1234567-sb1.app.netsuite.com) it will ask you to trust the domain. Approve it once — VS Code will remember your choice. The extension does not modify workbench.trustedDomains on your behalf.
Development
Build
npm install
npm run build
The build pipeline:
- Cleans
dist/
- Builds Vite webviews (Query Editor, Script Logs — both VS Code and NetSuite client bundles)
- Compiles extension TypeScript to
dist/ (CommonJS, ES2020)
- Copies SDF project templates to
dist/
Run Locally
- Open the
netsuite-repository-vscode folder in VS Code.
- Run
npm install and npm run build (or let the launch config build).
- Press F5 and choose Run NetSuite Repository Power Tools.
- In the Extension Development Host, open the NetSuite Repository sidebar or run NetSuite Repository: Open Entity Designer from the Command Palette.
Test
npm test
npm run test:coverage
Roadmap
- [x] Entity Designer — config generation, TypeScript interface preview, metadata bridge integration
- [x] Records Catalog — table, field, join, subrecord, and sublist browser
- [x] Script Logs — RESTlet-backed viewer with filtering and AI analysis
- [x] Query Editor — SuiteQL editor with completion, parsing, and error handling
- [x] Environment Compare — SDF object and FileCabinet diff between environments
- [x] Performance Tracker — execution performance panel and workspace adoption helpers
- [x] Copilot / Claude tools — language model tool integration
- [x] Setup & Maintenance — setup wizard, OAuth profile management, diagnostics
- [x] Marketplace packaging — published to the VS Code Marketplace
- [ ] Polish — validation rules, UX refinement
License
Copyright © 2026 Michael Young.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.