@altotyler/alto-rootstock-cli 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,38 +27,6 @@ Once a project is open, `Ctrl+Shift+P` → **"Tasks: Run Task"** exposes:
27
27
 
28
28
  ---
29
29
 
30
- ## Deploying and packaging
31
-
32
- ### 1. Create the GitHub repo
33
-
34
- Create a **private** repo: `github.com/alto-tyler/alto-rootstock-cli`
35
-
36
- This repo is separate from `rootstock-agent-distribution` — it's the CLI source code only.
37
-
38
- ### 2. Push the code
39
-
40
- ```bash
41
- cd alto-rootstock-cli
42
- git init
43
- git add .
44
- git commit -m "Initial release"
45
- git remote add origin git@github.com:alto-tyler/alto-rootstock-cli.git
46
- git push -u origin main
47
- ```
48
-
49
- ### 3. Publish a version
50
-
51
- Tag a release — GitHub Actions publishes it automatically to GitHub Packages:
52
-
53
- ```bash
54
- git tag v1.0.0
55
- git push origin v1.0.0
56
- ```
57
-
58
- The workflow in `.github/workflows/publish.yml` runs `npm publish` to npmjs.com using the `NPM_TOKEN` secret (add this in the repo Settings → Secrets → Actions).
59
-
60
- ---
61
-
62
30
  ## How users install it
63
31
 
64
32
  No auth required — the package is public on npmjs.com:
@@ -69,11 +37,11 @@ npm install -g @altotyler/alto-rootstock-cli
69
37
 
70
38
  After install, run `altors install` once to save your GitHub token for fetching skill files from the private distribution repo.
71
39
 
72
- After the one-time setup, updates are one command:
40
+ Updates are one command:
73
41
 
74
42
  ```bash
75
43
  npm update -g @altotyler/alto-rootstock-cli
76
- altors install # updates global VS Code agent files
44
+ altors install # re-fetches latest global VS Code agent files
77
45
  ```
78
46
 
79
47
  ---
@@ -85,11 +53,11 @@ Every time `altors` runs any command, it fetches `version.json` from the distrib
85
53
  ```
86
54
  ┌──────────────────────────────────────────────────────┐
87
55
  │ Update available: 1.0.0 → 1.2.0 │
88
- │ Run: npm update -g @altotyler/alto-rootstock-cli
56
+ │ Run: npm update -g @altotyler/alto-rootstock-cli
89
57
  └──────────────────────────────────────────────────────┘
90
58
  ```
91
59
 
92
- To support this, keep `version.json` in `rootstock-agent-distribution` updated with a `cliVersion` field:
60
+ To trigger update notices, bump `cliVersion` in `rootstock-agent-distribution/version.json`:
93
61
 
94
62
  ```json
95
63
  {
@@ -100,41 +68,41 @@ To support this, keep `version.json` in `rootstock-agent-distribution` updated w
100
68
 
101
69
  ---
102
70
 
71
+ ## Releasing a new CLI version
72
+
73
+ 1. Update `version` in `package.json`
74
+ 2. Commit and tag: `git tag v1.x.x && git push origin v1.x.x`
75
+ 3. GitHub Actions publishes to npmjs.com automatically (requires `NPM_TOKEN` secret in repo Settings → Secrets → Actions)
76
+ 4. Update `cliVersion` in `rootstock-agent-distribution/version.json`
77
+ 5. Users see the update prompt on their next `altors` command
78
+
79
+ ---
80
+
103
81
  ## Repository layout
104
82
 
105
83
  ```
106
- alto-rootstock-cli/ ← this repo (CLI source, publish to GitHub Packages)
107
- ├── bin/altors.js
84
+ alto-rootstock-cli/ ← this repo (CLI source, published to npmjs.com)
85
+ ├── bin/altors.js ← entry point + update notification
108
86
  ├── src/
109
- │ ├── commands/new.js
110
- │ ├── commands/update.js
111
- │ ├── commands/install.js
87
+ │ ├── commands/new.js ← prompts, runs sf project generate, injects skills
88
+ │ ├── commands/update.js ← updates skill files in current project
89
+ │ ├── commands/install.js ← installs global VS Code agent + saves GitHub token
112
90
  │ └── lib/
113
- │ ├── config.js ← ~/.alto-rootstock/config.json + ~/.npmrc auth
114
- │ ├── fetcher.js ← GitHub raw file fetcher (auth-aware)
115
- │ ├── scaffold.js writes IDE files into project
116
- │ └── updater.js ← version check (non-blocking)
117
- ├── project-template/ ← template files (publish to rootstock-agent-distribution)
118
- │ └── vscode/tasks.json
119
- └── .github/workflows/publish.yml
120
-
121
- rootstock-agent-distribution/ ← separate repo (skill files + version manifest)
122
- ├── version.json ← bump cliVersion here to trigger update notices
91
+ │ ├── config.js ← ~/.alto-rootstock/config.json token storage
92
+ │ ├── fetcher.js ← GitHub raw file fetcher (auth-aware)
93
+ │ ├── scaffold.js file manifest + writer
94
+ │ └── updater.js background version check
95
+ ├── project-template/
96
+ │ └── vscode/tasks.json ← injected into new projects for command palette tasks
97
+ └── .github/workflows/publish.yml ← auto-publishes to npmjs.com on git tag push
98
+
99
+ rootstock-agent-distribution/ ← separate private repo (skill files + version manifest)
100
+ ├── version.json ← bump cliVersion here to trigger update notices
123
101
  └── project-template/
124
102
  ├── claude/CLAUDE.md
125
- ├── claude/skills/*.md
103
+ ├── claude/skills/ ← 10 Rootstock skill files
126
104
  ├── cursor/rules/rootstock.mdc
127
105
  ├── github/agents/Rootstock Agent.agent.md
128
106
  ├── github/copilot-instructions.md
129
107
  └── vscode/mcp.json + tasks.json
130
108
  ```
131
-
132
- ---
133
-
134
- ## Releasing a new version
135
-
136
- 1. Update `version` in `package.json`
137
- 2. Commit and tag: `git tag v1.x.x && git push origin v1.x.x`
138
- 3. GitHub Actions publishes to GitHub Packages
139
- 4. Update `cliVersion` in `rootstock-agent-distribution/version.json`
140
- 5. Users see the update prompt on their next `altors` command
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altotyler/alto-rootstock-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CLI for creating and managing Rootstock Salesforce DX projects with AI agent scaffolding",
5
5
  "bin": {
6
6
  "altors": "./bin/altors.js"
@@ -4,11 +4,8 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
6
  const chalk = require('chalk');
7
- const prompts = require('prompts');
8
7
  const { fetchRemoteFile } = require('../lib/fetcher');
9
- const { getToken, saveToken } = require('../lib/config');
10
8
 
11
- // VS Code Copilot global agent directory by platform
12
9
  function getVsCodeAgentDir() {
13
10
  switch (process.platform) {
14
11
  case 'win32':
@@ -20,11 +17,6 @@ function getVsCodeAgentDir() {
20
17
  }
21
18
  }
22
19
 
23
- // Global Claude Code commands directory
24
- function getClaudeCommandsDir() {
25
- return path.join(os.homedir(), '.claude', 'commands');
26
- }
27
-
28
20
  const GLOBAL_FILES = [
29
21
  {
30
22
  remote: 'project-template/github/agents/Rootstock Agent.agent.md',
@@ -33,90 +25,12 @@ const GLOBAL_FILES = [
33
25
  },
34
26
  ];
35
27
 
36
- async function promptForToken() {
37
- console.log();
38
- console.log(chalk.yellow(' No GitHub token found.'));
39
- console.log(chalk.dim(' A token with read:packages scope is required to access the private distribution repo.'));
40
- console.log();
41
-
42
- const { token } = await prompts(
43
- {
44
- type: 'password',
45
- name: 'token',
46
- message: 'GitHub Personal Access Token (read:packages)',
47
- },
48
- { onCancel: () => process.exit(0) }
49
- );
50
-
51
- if (!token) return null;
52
-
53
- const { save } = await prompts(
54
- {
55
- type: 'confirm',
56
- name: 'save',
57
- message: 'Save token to ~/.alto-rootstock/config.json for future use?',
58
- initial: true,
59
- },
60
- { onCancel: () => {} }
61
- );
62
-
63
- if (save) {
64
- saveToken(token);
65
- console.log(` ${chalk.green('✓')} Token saved to ~/.alto-rootstock/config.json`);
66
- }
67
-
68
- // Also write to ~/.npmrc so npm update works without re-entering the token
69
- const npmrcPath = path.join(os.homedir(), '.npmrc');
70
- const npmrcLine = `//npm.pkg.github.com/:_authToken=${token}`;
71
- const npmrcScope = '@alto-tyler:registry=https://npm.pkg.github.com';
72
-
73
- let npmrcContent = '';
74
- if (fs.existsSync(npmrcPath)) {
75
- npmrcContent = fs.readFileSync(npmrcPath, 'utf8');
76
- }
77
-
78
- let updated = false;
79
- if (!npmrcContent.includes('//npm.pkg.github.com/:_authToken=')) {
80
- npmrcContent += `\n${npmrcLine}\n`;
81
- updated = true;
82
- } else {
83
- // Replace existing token line
84
- npmrcContent = npmrcContent.replace(/\/\/npm\.pkg\.github\.com\/:_authToken=.*/g, npmrcLine);
85
- updated = true;
86
- }
87
- if (!npmrcContent.includes('@alto-tyler:registry=')) {
88
- npmrcContent += `${npmrcScope}\n`;
89
- updated = true;
90
- }
91
-
92
- if (updated) {
93
- fs.writeFileSync(npmrcPath, npmrcContent.trimStart(), 'utf8');
94
- console.log(` ${chalk.green('✓')} ~/.npmrc updated — ${chalk.cyan('npm update -g @altotyler/alto-rootstock-cli')} will work without re-entering a token`);
95
- }
96
-
97
- process.env.GITHUB_TOKEN = token;
98
- return token;
99
- }
100
-
101
28
  async function run() {
102
29
  console.log();
103
30
  console.log(chalk.bold(' Rootstock: Global Install / Update'));
104
31
  console.log(chalk.dim(' ─────────────────────────────────────────────────'));
105
32
  console.log();
106
33
 
107
- let token = getToken();
108
- if (!token) {
109
- token = await promptForToken();
110
- if (!token) {
111
- console.error(chalk.red(' ✗ No token provided. Cannot access private distribution repo.'));
112
- process.exit(1);
113
- }
114
- } else {
115
- console.log(` ${chalk.green('✓')} GitHub token found`);
116
- }
117
-
118
- console.log();
119
-
120
34
  for (const entry of GLOBAL_FILES) {
121
35
  const target = entry.getTarget();
122
36
  const dir = path.dirname(target);
@@ -143,7 +57,7 @@ async function run() {
143
57
  console.log(chalk.dim(' 3. For project-level skills: run altors new or altors update in your project'));
144
58
  console.log();
145
59
  console.log(chalk.bold(' To update in future:'));
146
- console.log(chalk.cyan(' npm update -g @altotyler/alto-rootstock-cli'));
60
+ console.log(chalk.cyan(' npm update -g @altotyler/rootstock-cli'));
147
61
  console.log(chalk.cyan(' altors install'));
148
62
  console.log();
149
63
  }
@@ -6,7 +6,7 @@ const fs = require('fs');
6
6
  const chalk = require('chalk');
7
7
  const prompts = require('prompts');
8
8
  const { injectScaffolding } = require('../lib/scaffold');
9
- const { getToken } = require('../lib/config');
9
+
10
10
 
11
11
  function banner() {
12
12
  console.log();
@@ -28,17 +28,6 @@ function checkSfCli() {
28
28
  console.log(` ${chalk.green('✓')} Salesforce CLI detected ${chalk.dim(`(${version})`)}`);
29
29
  }
30
30
 
31
- function checkGithubToken() {
32
- const token = getToken();
33
- if (!token) {
34
- console.log();
35
- console.log(chalk.yellow(' ⚠ No GitHub token found.'));
36
- console.log(chalk.dim(' Skill files are hosted on a private repo.'));
37
- console.log(chalk.dim(' Set GITHUB_TOKEN or run:') + chalk.cyan(' altors install --save-token'));
38
- console.log();
39
- }
40
- return token;
41
- }
42
31
 
43
32
  async function promptProjectDetails() {
44
33
  console.log();
@@ -93,7 +82,6 @@ function runSfProjectGenerate(projectName, outputDir) {
93
82
  async function run() {
94
83
  banner();
95
84
  checkSfCli();
96
- checkGithubToken();
97
85
 
98
86
  const { projectName, outputDir } = await promptProjectDetails();
99
87
 
package/src/lib/config.js CHANGED
@@ -20,17 +20,4 @@ function load() {
20
20
  return { ...DEFAULTS };
21
21
  }
22
22
 
23
- function save(data) {
24
- if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
25
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
26
- }
27
-
28
- function getToken() {
29
- return process.env.GITHUB_TOKEN || load().token || null;
30
- }
31
-
32
- function saveToken(token) {
33
- save({ ...load(), token });
34
- }
35
-
36
- module.exports = { load, save, getToken, saveToken, CONFIG_FILE };
23
+ module.exports = { load, CONFIG_FILE };
@@ -1,17 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  const https = require('https');
4
- const { load, getToken } = require('./config');
4
+ const { load } = require('./config');
5
5
 
6
- function fetchUrl(url, token) {
6
+ function fetchUrl(url) {
7
7
  return new Promise((resolve, reject) => {
8
8
  const opts = new URL(url);
9
9
  const headers = { 'User-Agent': 'alto-rootstock-cli' };
10
- if (token) headers['Authorization'] = `Bearer ${token}`;
11
10
 
12
11
  https.get({ hostname: opts.hostname, path: opts.pathname + opts.search, headers }, (res) => {
13
12
  if (res.statusCode === 302 || res.statusCode === 301) {
14
- return fetchUrl(res.headers.location, token).then(resolve).catch(reject);
13
+ return fetchUrl(res.headers.location).then(resolve).catch(reject);
15
14
  }
16
15
  if (res.statusCode !== 200) {
17
16
  res.resume();
@@ -27,9 +26,7 @@ function fetchUrl(url, token) {
27
26
 
28
27
  async function fetchRemoteFile(remotePath) {
29
28
  const { baseUrl } = load();
30
- const token = getToken();
31
- const url = `${baseUrl}/${remotePath}`;
32
- return fetchUrl(url, token);
29
+ return fetchUrl(`${baseUrl}/${remotePath}`);
33
30
  }
34
31
 
35
32
  async function fetchRemoteJson(remotePath) {