offgrid-ai 0.3.6 → 0.3.8

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.
Files changed (3) hide show
  1. package/install.sh +37 -9
  2. package/package.json +1 -1
  3. package/src/cli.mjs +49 -2
package/install.sh CHANGED
@@ -123,15 +123,38 @@ if $DRY_RUN; then
123
123
  exit 0
124
124
  fi
125
125
 
126
+ # ── Determine npm global bin directory ──────────────────────────────────────
127
+ # npm bin -g was removed in npm v10+. Fall back to $(npm prefix -g)/bin.
128
+
129
+ NPM_BIN=""
130
+ if command -v npm &>/dev/null; then
131
+ # Try the modern way first, then legacy
132
+ NPM_PREFIX="$(npm prefix -g 2>/dev/null || true)"
133
+ if [[ -n "$NPM_PREFIX" ]]; then
134
+ NPM_BIN="${NPM_PREFIX}/bin"
135
+ fi
136
+ # Validate: the binary should exist there
137
+ if [[ ! -d "$NPM_BIN" ]]; then
138
+ NPM_BIN=""
139
+ fi
140
+ fi
141
+
126
142
  # ── Add npm global bin to PATH if needed ────────────────────────────────────
127
143
 
128
- NPM_BIN="$(npm bin -g 2>/dev/null)"
144
+ INSTALLED_VERSION=""
145
+
146
+ if [[ -n "$NPM_BIN" && -x "$NPM_BIN/offgrid-ai" ]]; then
147
+ # Get version
148
+ INSTALLED_VERSION="$(OFFGRID_NO_UPDATE_CHECK=1 "$NPM_BIN/offgrid-ai" version 2>/dev/null || echo "")"
129
149
 
130
- if ! command -v offgrid-ai &>/dev/null; then
131
- if [[ -n "$NPM_BIN" && -x "$NPM_BIN/offgrid-ai" ]]; then
132
- # Add to current session
150
+ if command -v offgrid-ai &>/dev/null; then
151
+ # Already on PATH nothing to do
152
+ ok "offgrid-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }installed at $(command -v offgrid-ai)"
153
+ else
154
+ # Not on PATH — add it
133
155
  export PATH="$NPM_BIN:$PATH"
134
156
  ok "Added $NPM_BIN to PATH for this session"
157
+ ok "offgrid-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }installed"
135
158
 
136
159
  # Add to shell config for future sessions (pick first existing or .zshrc)
137
160
  ADDED_TO_RC=false
@@ -152,13 +175,20 @@ if ! command -v offgrid-ai &>/dev/null; then
152
175
  if ! $ADDED_TO_RC; then
153
176
  warn "$NPM_BIN is already in a shell config file — restart your terminal to use offgrid-ai"
154
177
  fi
178
+ fi
179
+ else
180
+ # Fallback: try to find it anywhere on PATH after install
181
+ if command -v offgrid-ai &>/dev/null; then
182
+ INSTALLED_VERSION="$(offgrid-ai version 2>/dev/null || echo "")"
183
+ ok "offgrid-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }installed at $(command -v offgrid-ai)"
155
184
  else
156
185
  echo ""
157
- warn "offgrid-ai was installed but the binary wasn't found."
186
+ warn "offgrid-ai was installed but could not be found."
158
187
  echo " Restart your terminal and run: offgrid-ai"
188
+ echo " Or run: npx offgrid-ai"
159
189
  echo ""
160
190
  printf "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
161
- printf "${BOLD}${GREEN} offgrid-ai is ready!${RESET}\n"
191
+ printf "${BOLD}${GREEN} offgrid-ai is installed!${RESET}\n"
162
192
  printf "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
163
193
  echo ""
164
194
  echo " Run: offgrid-ai"
@@ -167,13 +197,11 @@ if ! command -v offgrid-ai &>/dev/null; then
167
197
  fi
168
198
  fi
169
199
 
170
- ok "offgrid-ai installed at $(command -v offgrid-ai)"
171
-
172
200
  # ── Done ─────────────────────────────────────────────────────────────────────
173
201
 
174
202
  echo ""
175
203
  printf "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
176
- printf "${BOLD}${GREEN} offgrid-ai is ready!${RESET}\n"
204
+ printf "${BOLD}${GREEN} offgrid-ai ${INSTALLED_VERSION:+v${INSTALLED_VERSION} }is ready!${RESET}\n"
177
205
  printf "${BOLD}${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
178
206
  echo ""
179
207
  echo " First run will walk you through setting up everything you need"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offgrid-ai",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Privacy-first CLI for running local LLMs — discover, configure, run, benchmark",
5
5
  "author": "Eeshan Srivastava (https://eeshans.com)",
6
6
  "type": "module",
package/src/cli.mjs CHANGED
@@ -789,6 +789,7 @@ async function uninstallCommand(argv) {
789
789
  // Non-interactive / forced: remove everything
790
790
  await removeDataDir();
791
791
  await removeSelf();
792
+ await removeShellPath();
792
793
  return;
793
794
  }
794
795
 
@@ -825,7 +826,8 @@ async function uninstallCommand(argv) {
825
826
  // Remove the npm package
826
827
  const confirmUninstall = await prompt.yesNo("Uninstall offgrid-ai npm package?", true);
827
828
  if (confirmUninstall) {
828
- removeSelf();
829
+ await removeSelf();
830
+ await removeShellPath();
829
831
  } else {
830
832
  console.log(pc.dim("Cancelled."));
831
833
  }
@@ -849,6 +851,51 @@ async function removeDataDir() {
849
851
  }
850
852
  }
851
853
 
854
+ async function removeShellPath() {
855
+ const { readFile, writeFile } = await import("node:fs/promises");
856
+ const { homedir } = await import("node:os");
857
+ const { promisify } = await import("node:util");
858
+ const { execFile } = await import("node:child_process");
859
+ let npmBin;
860
+ try {
861
+ const { stdout } = await promisify(execFile)("npm", ["bin", "-g"]);
862
+ npmBin = stdout.trim();
863
+ } catch { return; }
864
+ if (!npmBin) return;
865
+
866
+ const marker = "# Added by offgrid-ai installer";
867
+ const pathLine = `export PATH="${npmBin}:$PATH"`;
868
+ const rcFiles = [`${homedir()}/.zshrc`, `${homedir()}/.bashrc`, `${homedir()}/.bash_profile`];
869
+ let cleaned = false;
870
+
871
+ for (const rcFile of rcFiles) {
872
+ if (!existsSync(rcFile)) continue;
873
+ let content;
874
+ try { content = await readFile(rcFile, "utf8"); } catch { continue; }
875
+ if (!content.includes(npmBin) && !content.includes(marker)) continue;
876
+
877
+ const lines = content.split("\n");
878
+ const filtered = lines.filter((line, i) => {
879
+ // Remove the marker comment line
880
+ if (line.trim() === marker) return false;
881
+ // Remove the PATH export line added by the installer
882
+ if (line.trim() === pathLine) return false;
883
+ // Also remove a blank line that immediately precedes the marker (formatter)
884
+ if (i + 1 < lines.length && lines[i + 1].trim() === marker && line.trim() === "") return false;
885
+ return true;
886
+ });
887
+
888
+ if (filtered.length !== lines.length) {
889
+ await writeFile(rcFile, filtered.join("\n").replace(/\n{3,}/g, "\n\n") + "\n", "utf8");
890
+ console.log(pc.green(`✓ Cleaned PATH from ${rcFile}`));
891
+ cleaned = true;
892
+ }
893
+ }
894
+ if (!cleaned) {
895
+ console.log(pc.dim("No offgrid-ai PATH entries found in shell configs."));
896
+ }
897
+ }
898
+
852
899
  async function removeSelf() {
853
900
  console.log(pc.cyan("\nUninstalling offgrid-ai..."));
854
901
  const { spawn: spawnUninstall } = await import("node:child_process");
@@ -932,7 +979,7 @@ Usage:
932
979
  offgrid-ai Pick a model and run it
933
980
  offgrid-ai status Show running local models
934
981
  offgrid-ai stop Stop a running server (or: offgrid-ai stop <id>)
935
- offgrid-ai uninstall Remove offgrid-ai (optionally keep profiles)
982
+ offgrid-ai uninstall Remove offgrid-ai, clean up PATH, optionally keep profiles
936
983
  offgrid-ai help Show this help
937
984
  offgrid-ai version Show version
938
985