diff --git a/.github/workflows/release_build_infisical_cli.yml b/.github/workflows/release_build_infisical_cli.yml
index 02c3492376..3a3b384f39 100644
--- a/.github/workflows/release_build_infisical_cli.yml
+++ b/.github/workflows/release_build_infisical_cli.yml
@@ -10,8 +10,7 @@ on:
permissions:
contents: write
- # packages: write
- # issues: write
+
jobs:
cli-integration-tests:
name: Run tests before deployment
@@ -26,6 +25,63 @@ jobs:
CLI_TESTS_USER_PASSWORD: ${{ secrets.CLI_TESTS_USER_PASSWORD }}
CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE: ${{ secrets.CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE }}
+ npm-release:
+ runs-on: ubuntu-20.04
+ env:
+ working-directory: ./npm
+ needs:
+ - cli-integration-tests
+ - goreleaser
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Extract version
+ run: |
+ VERSION=$(echo ${{ github.ref_name }} | sed 's/infisical-cli\/v//')
+ echo "Version extracted: $VERSION"
+ echo "CLI_VERSION=$VERSION" >> $GITHUB_ENV
+
+ - name: Print version
+ run: echo ${{ env.CLI_VERSION }}
+
+ - name: Setup Node
+ uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
+ with:
+ node-version: 20
+ cache: "npm"
+ cache-dependency-path: ./npm/package-lock.json
+ - name: Install dependencies
+ working-directory: ${{ env.working-directory }}
+ run: npm install --ignore-scripts
+
+ - name: Set NPM version
+ working-directory: ${{ env.working-directory }}
+ run: npm version ${{ env.CLI_VERSION }} --allow-same-version --no-git-tag-version
+
+ - name: Setup NPM
+ working-directory: ${{ env.working-directory }}
+ run: |
+ echo 'registry="https://registry.npmjs.org/"' > ./.npmrc
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ./.npmrc
+
+ echo 'registry="https://registry.npmjs.org/"' > ~/.npmrc
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+
+ - name: Pack NPM
+ working-directory: ${{ env.working-directory }}
+ run: npm pack
+
+ - name: Publish NPM
+ working-directory: ${{ env.working-directory }}
+ run: npm publish --tarball=./infisical-sdk-${{github.ref_name}} --access public --registry=https://registry.npmjs.org/
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+
goreleaser:
runs-on: ubuntu-20.04
needs: [cli-integration-tests]
diff --git a/.gitignore b/.gitignore
index e76fd0c11b..f2a23324b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,3 +71,5 @@ frontend-build
cli/infisical-merge
cli/test/infisical-merge
/backend/binary
+
+/npm/bin
diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx
index ab913ec1af..397d1f474f 100644
--- a/docs/cli/overview.mdx
+++ b/docs/cli/overview.mdx
@@ -9,7 +9,7 @@ You can use it across various environments, whether it's local development, CI/C
## Installation
-
+
Use [brew](https://brew.sh/) package manager
```bash
@@ -21,9 +21,8 @@ You can use it across various environments, whether it's local development, CI/C
```bash
brew update && brew upgrade infisical
```
-
-
-
+
+
Use [Scoop](https://scoop.sh/) package manager
```bash
@@ -40,7 +39,20 @@ You can use it across various environments, whether it's local development, CI/C
scoop update infisical
```
-
+
+
+ Use [NPM](https://www.npmjs.com/) package manager
+
+ ```bash
+ npm install -g @infisical/cli
+ ```
+
+ ### Updates
+
+ ```bash
+ npm update -g @infisical/cli
+ ```
+
Install prerequisite
```bash
diff --git a/npm/.eslintrc.json b/npm/.eslintrc.json
new file mode 100644
index 0000000000..de8743bbbf
--- /dev/null
+++ b/npm/.eslintrc.json
@@ -0,0 +1,9 @@
+{
+ "env": {
+ "es6": true,
+ "node": true
+ },
+ "parserOptions": {
+ "ecmaVersion": "latest"
+ }
+}
diff --git a/npm/README.md b/npm/README.md
new file mode 100644
index 0000000000..b64b02ccde
--- /dev/null
+++ b/npm/README.md
@@ -0,0 +1,71 @@
+Infisical
+
+
The open-source secret management platform: Sync secrets/configs across your team/infrastructure and prevent secret leaks.
+
+
+
+
+
+
+
+### Introduction
+
+**[Infisical](https://infisical.com)** is the open source secret management platform that teams use to centralize their application configuration and secrets like API keys and database credentials as well as manage their internal PKI.
+
+We're on a mission to make security tooling more accessible to everyone, not just security teams, and that means redesigning the entire developer experience from ground up.
+
+
+### Installation
+
+The Infisical CLI NPM package serves as a new installation method in addition to our [existing installation methods](https://infisical.com/docs/cli/overview).
+
+After installing the CLI with the command below, you'll be able to use the infisical CLI across your machine.
+
+```bash
+$ npm install -g @infisical/cli
+```
+
+Full example:
+```bash
+# Install the Infisical CLI
+$ npm install -g @infisical/cli
+
+# Authenticate with the Infisical CLI
+$ infisical login
+
+# Initialize your Infisical CLI
+$ infisical init
+
+# List your secrets with Infisical CLI
+$ infisical secrets
+```
+
+
+### Documentation
+Our full CLI documentation can be found [here](https://infisical.com/docs/cli/usage).
\ No newline at end of file
diff --git a/npm/package-lock.json b/npm/package-lock.json
new file mode 100644
index 0000000000..872adcf77c
--- /dev/null
+++ b/npm/package-lock.json
@@ -0,0 +1,112 @@
+{
+ "name": "@infisical/cli",
+ "version": "0.14.3",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@infisical/cli",
+ "version": "0.14.3",
+ "hasInstallScript": true,
+ "dependencies": {
+ "tar": "^6.2.0"
+ },
+ "bin": {
+ "infisical": "bin/infisical"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ }
+}
diff --git a/npm/package.json b/npm/package.json
new file mode 100644
index 0000000000..31859c5988
--- /dev/null
+++ b/npm/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@infisical/cli",
+ "private": false,
+ "version": "0.0.0",
+ "keywords": [
+ "infisical",
+ "cli",
+ "command-line"
+ ],
+ "bin": {
+ "infisical": "./bin/infisical"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Infisical/infisical.git"
+ },
+ "author": "Infisical Inc, ",
+
+ "scripts": {
+ "postinstall": "node src/index.cjs"
+ },
+ "dependencies": {
+ "tar": "^6.2.0"
+ }
+}
diff --git a/npm/src/index.cjs b/npm/src/index.cjs
new file mode 100644
index 0000000000..28fe0979b9
--- /dev/null
+++ b/npm/src/index.cjs
@@ -0,0 +1,103 @@
+const childProcess = require("child_process");
+const fs = require("fs");
+const stream = require("node:stream");
+const tar = require("tar");
+const path = require("path");
+const zlib = require("zlib");
+const packageJSON = require("../package.json");
+
+const supportedPlatforms = ["linux", "darwin", "win32", "freebsd"];
+const outputDir = "bin";
+
+const getPlatform = () => {
+ const platform = process.platform;
+ if (!supportedPlatforms.includes(platform)) {
+ console.error("Your platform doesn't seem to be of type darwin, linux or windows");
+ process.exit(1);
+ }
+ return platform;
+};
+
+const getArchitecture = () => {
+ const architecture = process.arch;
+ let arch = "";
+
+ if (architecture === "x64" || architecture === "amd64") {
+ arch = "amd64";
+ } else if (architecture === "arm64") {
+ arch = "arm64";
+ } else if (architecture === "arm") {
+ // If the platform is Linux, we should find the exact ARM version, otherwise we default to armv7 which is the most common
+ if (process.platform === "linux" || process.platform === "freebsd") {
+ const output = childProcess.execSync("uname -m").toString().trim();
+
+ const armVersions = ["armv5", "armv6", "armv7"];
+
+ const armVersion = armVersions.find(version => output.startsWith(version));
+
+ if (armVersion) {
+ arch = armVersion;
+ } else {
+ arch = "armv7";
+ }
+ } else {
+ arch = "armv7";
+ }
+ } else if (architecture === "ia32") {
+ arch = "i386";
+ } else {
+ console.error("Your architecture doesn't seem to be supported. Your architecture is", architecture);
+ process.exit(1);
+ }
+
+ return arch;
+};
+
+async function main() {
+ const PLATFORM = getPlatform();
+ const ARCH = getArchitecture();
+ const NUMERIC_RELEASE_VERSION = packageJSON.version;
+ const LATEST_RELEASE_VERSION = `v${NUMERIC_RELEASE_VERSION}`;
+ const downloadLink = `https://github.com/Infisical/infisical/releases/download/infisical-cli/${LATEST_RELEASE_VERSION}/infisical_${NUMERIC_RELEASE_VERSION}_${PLATFORM}_${ARCH}.tar.gz`;
+
+ // Ensure the output directory exists
+ if (!fs.existsSync(outputDir)) {
+ fs.mkdirSync(outputDir);
+ }
+
+ // Download the latest CLI binary
+ try {
+ const response = await fetch(downloadLink, {
+ headers: {
+ Accept: "application/octet-stream"
+ }
+ });
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch: ${response.status} - ${response.statusText}`);
+ }
+
+ await new Promise((resolve, reject) => {
+ const outStream = stream.Readable.fromWeb(response.body)
+ .pipe(zlib.createGunzip())
+ .pipe(
+ tar.x({
+ C: path.join(outputDir),
+ filter: path => path === "infisical"
+ })
+ );
+
+ outStream.on("error", reject);
+ outStream.on("close", resolve);
+ });
+
+ // Give the binary execute permissions if we're not on Windows
+ if (PLATFORM !== "win32") {
+ fs.chmodSync(path.join(outputDir, "infisical"), "755");
+ }
+ } catch (error) {
+ console.error("Error downloading or extracting Infisical CLI:", error);
+ process.exit(1);
+ }
+}
+main();