├── .env.example
├── .github
└── workflows
│ ├── npm-build.yml
│ └── npm-publish.yml
├── .gitignore
├── .idx
└── dev.nix
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── bin
└── index.js
├── package.json
├── pnpm-lock.yaml
├── screenshot.png
├── src
├── commands
│ ├── apps.js
│ ├── auth.js
│ ├── files.js
│ ├── init.js
│ ├── shell.js
│ ├── sites.js
│ └── subdomains.js
├── commons.js
├── crypto.js
├── executor.js
├── modules
│ └── ErrorModule.js
└── utils.js
└── tests
├── login.test.js
└── utils.test.js
/.env.example:
--------------------------------------------------------------------------------
1 | # Default Puter's API
2 | PUTER_API_BASE='http://api.puter.localhost:4100'
3 | PUTER_BASE_URL='http://puter.localhost:4100'
--------------------------------------------------------------------------------
/.github/workflows/npm-build.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node on every push
2 | name: Build package
3 |
4 | on: push
5 |
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 |
10 | strategy:
11 | matrix:
12 | node-version: ['18.x', '20.x', '23.x']
13 | steps:
14 | - uses: actions/checkout@v4
15 | - name: Install pnpm
16 | uses: pnpm/action-setup@v4
17 | with:
18 | version: 10
19 | - name: Use Node.js ${{ matrix.node-version }}
20 | uses: actions/setup-node@v4
21 | with:
22 | node-version: ${{ matrix.node-version }}
23 | cache: 'pnpm'
24 | - name: Install dependencies
25 | run: pnpm install
26 | - name: Run tests & coverage
27 | run: pnpm run coverage
28 | - name: Upload coverage reports to Codecov
29 | uses: codecov/codecov-action@v5
30 | with:
31 | token: ${{ secrets.CODECOV_TOKEN }}
32 | slug: HeyPuter/puter-cli
33 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3 |
4 | name: Publish package
5 |
6 | on: push
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 | - uses: actions/setup-node@v4
14 | with:
15 | node-version: 20
16 | - run: npm ci
17 | - run: npm test
18 |
19 | publish-npm:
20 | needs: build
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: actions/checkout@v4
24 | - uses: actions/setup-node@v4
25 | with:
26 | node-version: 20
27 | registry-url: https://registry.npmjs.org/
28 | - run: npm ci
29 | - run: npm publish
30 | env:
31 | NODE_AUTH_TOKEN: ${{secrets.npm_token}}
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dev
2 | .yarn/
3 | !.yarn/releases
4 | .vscode/*
5 | !.vscode/launch.json
6 | !.vscode/*.code-snippets
7 | .idea/workspace.xml
8 | .idea/usage.statistics.xml
9 | .idea/shelf
10 |
11 | # deps
12 | node_modules/
13 |
14 | # env
15 | .env
16 | .env.production
17 |
18 | # logs
19 | logs/
20 | *.log
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | pnpm-debug.log*
25 | lerna-debug.log*
26 |
27 | # misc
28 | .DS_Store
29 |
30 | # code coverage
31 | **/coverage/
32 |
--------------------------------------------------------------------------------
/.idx/dev.nix:
--------------------------------------------------------------------------------
1 | # To learn more about how to use Nix to configure your environment
2 | # see: https://developers.google.com/idx/guides/customize-idx-env
3 | { pkgs, ... }: {
4 | # Which nixpkgs channel to use.
5 | channel = "stable-24.05"; # or "unstable"
6 | # Use https://search.nixos.org/packages to find packages
7 | packages = [
8 | # pkgs.go
9 | # pkgs.python311
10 | # pkgs.python311Packages.pip
11 | pkgs.nodejs_20
12 | pkgs.nodePackages.nodemon
13 | ];
14 | # Sets environment variables in the workspace
15 | env = {};
16 | idx = {
17 | # Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
18 | extensions = [
19 | # "vscodevim.vim"
20 | ];
21 | # Enable previews
22 | previews = {
23 | enable = true;
24 | previews = {
25 | # web = {
26 | # # Example: run "npm run dev" with PORT set to IDX's defined port for previews,
27 | # # and show it in IDX's web preview panel
28 | # command = ["npm" "run" "dev"];
29 | # manager = "web";
30 | # env = {
31 | # # Environment variables to set for your server
32 | # PORT = "$PORT";
33 | # };
34 | # };
35 | };
36 | };
37 | # Workspace lifecycle hooks
38 | workspace = {
39 | # Runs when a workspace is first created
40 | onCreate = {
41 | # Example: install JS dependencies from NPM
42 | # npm-install = "npm install";
43 | # Open editors for the following files by default, if they exist:
44 | default.openFiles = [ ".idx/dev.nix" "README.md" ];
45 | };
46 | # Runs when the workspace is (re)started
47 | onStart = {
48 | # Example: start a background task to watch and re-build backend code
49 | # watch-backend = "npm run watch-backend";
50 | };
51 | };
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### Changelog
2 |
3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4 |
5 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6 |
7 | #### [v1.8.0](https://github.com/HeyPuter/puter-cli/compare/v1.7.3...v1.8.0)
8 |
9 | - feat(files): add edit command to modify remote files with local editor [`220b07c`](https://github.com/HeyPuter/puter-cli/commit/220b07c79fa9e9ab2e0e668cfbd7e5260c9746a2)
10 |
11 | #### [v1.7.3](https://github.com/HeyPuter/puter-cli/compare/v1.7.2...v1.7.3)
12 |
13 | > 16 March 2025
14 |
15 | - fix: absolute remote path treated as relative in update #10 [`cb716a3`](https://github.com/HeyPuter/puter-cli/commit/cb716a37afdd9f552c53244a3eb63d7a649e244c)
16 |
17 | #### [v1.7.2](https://github.com/HeyPuter/puter-cli/compare/v1.7.1...v1.7.2)
18 |
19 | > 4 March 2025
20 |
21 | - fix: mv command for both rename/move files [`0b944c8`](https://github.com/HeyPuter/puter-cli/commit/0b944c8295f615427bd90d19a6058b2053c1b3dc)
22 |
23 | #### [v1.7.1](https://github.com/HeyPuter/puter-cli/compare/v1.7.0...v1.7.1)
24 |
25 | > 4 March 2025
26 |
27 | - fix: update command [`38ca9e8`](https://github.com/HeyPuter/puter-cli/commit/38ca9e824642cbf8b1ffdb0d2a6e5426f84c7371)
28 | - docs: update README [`6e658f6`](https://github.com/HeyPuter/puter-cli/commit/6e658f6a117ee1ba206768905d53fb61c78e136d)
29 |
30 | #### [v1.7.0](https://github.com/HeyPuter/puter-cli/compare/v1.6.1...v1.7.0)
31 |
32 | > 16 February 2025
33 |
34 | - feat: save auth token when login [`55b32b7`](https://github.com/HeyPuter/puter-cli/commit/55b32b7feca050902f4470f06af38f81d3299e6a)
35 | - fix: create app from host shell [`30e5028`](https://github.com/HeyPuter/puter-cli/commit/30e5028d831d26349e3ae2fc8e34921693b5702c)
36 |
37 | #### [v1.6.1](https://github.com/HeyPuter/puter-cli/compare/v1.6.0...v1.6.1)
38 |
39 | > 16 February 2025
40 |
41 | - fix: set subdomain when creating a site [`6329ed1`](https://github.com/HeyPuter/puter-cli/commit/6329ed1c766b8eb722ac8c03c9ffe61dbba4a66c)
42 |
43 | #### [v1.6.0](https://github.com/HeyPuter/puter-cli/compare/v1.5.7...v1.6.0)
44 |
45 | > 16 February 2025
46 |
47 | - feat: improve init command [`2bd51ee`](https://github.com/HeyPuter/puter-cli/commit/2bd51ee01d0636b7979a9f55d3c746287c3b512a)
48 | - chore: improve error message [`46fb3b0`](https://github.com/HeyPuter/puter-cli/commit/46fb3b063c1c74d0006138cd400b6ad207e784d9)
49 | - chore: update package repo [`f6960ed`](https://github.com/HeyPuter/puter-cli/commit/f6960ed6f8e6fb793a6b8340476ab22778b44c14)
50 |
51 | #### [v1.5.7](https://github.com/HeyPuter/puter-cli/compare/v1.5.6...v1.5.7)
52 |
53 | > 16 February 2025
54 |
55 | - chore: clean unused [`8477dc2`](https://github.com/HeyPuter/puter-cli/commit/8477dc294773c99270a83dc22ae602abe92621cf)
56 |
57 | #### [v1.5.6](https://github.com/HeyPuter/puter-cli/compare/v1.5.5...v1.5.6)
58 |
59 | > 15 February 2025
60 |
61 | - fix: default api values [`146eda5`](https://github.com/HeyPuter/puter-cli/commit/146eda560da02f21a04523333b615c9ee2372322)
62 |
63 | #### [v1.5.5](https://github.com/HeyPuter/puter-cli/compare/v1.5.4...v1.5.5)
64 |
65 | > 13 February 2025
66 |
67 | - fix: improve error handling [`d1fa91d`](https://github.com/HeyPuter/puter-cli/commit/d1fa91db09f08238c6be684ffe4688a0064f06cd)
68 |
69 | #### [v1.5.4](https://github.com/HeyPuter/puter-cli/compare/v1.5.3...v1.5.4)
70 |
71 | > 13 February 2025
72 |
73 | - Remove "subdomain deletion" under Known Issues in README.md [`#8`](https://github.com/HeyPuter/puter-cli/pull/8)
74 | - dev: add last-error command, context, and modules [`#7`](https://github.com/HeyPuter/puter-cli/pull/7)
75 | - fix: delete a subdomain error message [`ed676dc`](https://github.com/HeyPuter/puter-cli/commit/ed676dc9d1364fabf242098e142a84c305dff177)
76 | - ci: fix timezone issue [`8ee6a66`](https://github.com/HeyPuter/puter-cli/commit/8ee6a66db36f7ca00eb81a12c8bac094e057f534)
77 | - ci: simplify timezone check [`ecf3bb9`](https://github.com/HeyPuter/puter-cli/commit/ecf3bb98bec5c093c23772280e3ee52aab8f3e8f)
78 |
79 | #### [v1.5.3](https://github.com/HeyPuter/puter-cli/compare/v1.5.2...v1.5.3)
80 |
81 | > 7 February 2025
82 |
83 | - refactor: early return in fallback behavior [`#6`](https://github.com/HeyPuter/puter-cli/pull/6)
84 | - fix: ignore undefined appDir when listing sites [`#5`](https://github.com/HeyPuter/puter-cli/pull/5)
85 | - fix: use array args when calling DeleteSubdomain [`#4`](https://github.com/HeyPuter/puter-cli/pull/4)
86 | - Update README.md [`#3`](https://github.com/HeyPuter/puter-cli/pull/3)
87 | - fix: improve app uuid check [`49dcc7f`](https://github.com/HeyPuter/puter-cli/commit/49dcc7f1220a58987601e8054b0d4a450cd02afe)
88 | - fix: potential timezone issues [`ba0e4b1`](https://github.com/HeyPuter/puter-cli/commit/ba0e4b183efb82a0c252e5c6250d976f1efe19cd)
89 |
90 | #### [v1.5.2](https://github.com/HeyPuter/puter-cli/compare/v1.5.1...v1.5.2)
91 |
92 | > 6 February 2025
93 |
94 | - chore: clean unused [`e5c7fcc`](https://github.com/HeyPuter/puter-cli/commit/e5c7fcca3096b4b2c0659d84d8de63dce039a765)
95 | - chore: more details [`0a25a2f`](https://github.com/HeyPuter/puter-cli/commit/0a25a2fb7efa9a67033b4e483305da44a68f2c9a)
96 | - docs: badge version [`503bc66`](https://github.com/HeyPuter/puter-cli/commit/503bc6667666b14f85245887a3bf2071711dc4e1)
97 |
98 | #### [v1.5.1](https://github.com/HeyPuter/puter-cli/compare/v1.5.0...v1.5.1)
99 |
100 | > 5 February 2025
101 |
102 | - imporve listing uid [`e2573f8`](https://github.com/HeyPuter/puter-cli/commit/e2573f83df6b47d8ab32ffc66ab19a9c984dd250)
103 |
104 | #### [v1.5.0](https://github.com/HeyPuter/puter-cli/compare/v1.4.4...v1.5.0)
105 |
106 | > 5 February 2025
107 |
108 | - fix: improve version check [`f3ea79e`](https://github.com/HeyPuter/puter-cli/commit/f3ea79e3156632f892558489dfd34b1119948a48)
109 | - update README [`79b381c`](https://github.com/HeyPuter/puter-cli/commit/79b381c57935cae5ffb9edf5ad11aca395ae8f8d)
110 |
111 | #### [v1.4.4](https://github.com/HeyPuter/puter-cli/compare/v1.4.3...v1.4.4)
112 |
113 | > 4 February 2025
114 |
115 | - simplify failed login [`bbf8a42`](https://github.com/HeyPuter/puter-cli/commit/bbf8a429c1d2a64fbb03fb42f461bcc1a32c8379)
116 |
117 | #### [v1.4.3](https://github.com/HeyPuter/puter-cli/compare/v1.4.2...v1.4.3)
118 |
119 | > 2 February 2025
120 |
121 | - fix: show disk usage [`dfd0ca3`](https://github.com/HeyPuter/puter-cli/commit/dfd0ca302f459b7295593c8d0147df15e488c963)
122 |
123 | #### [v1.4.2](https://github.com/HeyPuter/puter-cli/compare/v1.4.1...v1.4.2)
124 |
125 | > 30 January 2025
126 |
127 | - license to MIT [`ed0c7ce`](https://github.com/HeyPuter/puter-cli/commit/ed0c7cefba242a5d8fe701cddf5adbe32121bca7)
128 | - codecov: setup & badge [`7c4211b`](https://github.com/HeyPuter/puter-cli/commit/7c4211b6ea7b882485e3dfbaa17887a2d1fabccc)
129 | - changelog: update license [`dcf8d23`](https://github.com/HeyPuter/puter-cli/commit/dcf8d232160cf74d13267baa07a8f36578df9443)
130 |
131 | #### [v1.4.1](https://github.com/HeyPuter/puter-cli/compare/v1.4.0...v1.4.1)
132 |
133 | > 27 January 2025
134 |
135 | - feat: init command will scaffold new project [`c61d3f8`](https://github.com/HeyPuter/puter-cli/commit/c61d3f8669d66eb1a869db38b877d226d00b8aca)
136 | - changelog: update [`c09aa17`](https://github.com/HeyPuter/puter-cli/commit/c09aa179bd0ad2f437bdf779916050c2496424cd)
137 |
138 | #### [v1.4.0](https://github.com/HeyPuter/puter-cli/compare/v1.3.0...v1.4.0)
139 |
140 | > 26 January 2025
141 |
142 | - offline mode to get version [`d3c1dc2`](https://github.com/HeyPuter/puter-cli/commit/d3c1dc275bf8a1f38f083c8cdb066fb884a08138)
143 | - changelog: update [`f0cc1e3`](https://github.com/HeyPuter/puter-cli/commit/f0cc1e36b2b246d65a88f32c626942c0e15ac245)
144 |
145 | #### [v1.3.0](https://github.com/HeyPuter/puter-cli/compare/v1.2.1...v1.3.0)
146 |
147 | > 22 January 2025
148 |
149 | - ci: simplify workflow [`757b41c`](https://github.com/HeyPuter/puter-cli/commit/757b41caa62dc71946e7f1ffb34a32f2871248e0)
150 | - test: setup coverage [`2dd6500`](https://github.com/HeyPuter/puter-cli/commit/2dd650088ad9ecb6f7f9cd60b3dab80d48ac2611)
151 | - ci: update packages [`b346932`](https://github.com/HeyPuter/puter-cli/commit/b346932c4b6af2d8e43279ad3f35c45e451fd9f0)
152 |
153 | #### [v1.2.1](https://github.com/HeyPuter/puter-cli/compare/v1.2.0...v1.2.1)
154 |
155 | > 18 January 2025
156 |
157 | - feat: update changelog [`028ca0c`](https://github.com/HeyPuter/puter-cli/commit/028ca0cf72e09bb63468d2b0a0ba7602d3b870ad)
158 | - feat: auto-update changelog [`3004bed`](https://github.com/HeyPuter/puter-cli/commit/3004beda6afcf68cc916d544a45be85fa7e658e3)
159 |
160 | #### [v1.2.0](https://github.com/HeyPuter/puter-cli/compare/v1.1.5...v1.2.0)
161 |
162 | > 18 January 2025
163 |
164 | - ci: attempt to fix npm install [`32fc508`](https://github.com/HeyPuter/puter-cli/commit/32fc508c4807119de485926674274b70e034288f)
165 | - feat: basic history command [`18da28c`](https://github.com/HeyPuter/puter-cli/commit/18da28c83aa0760128d7b18e66e6b4d2b08b48d3)
166 | - chore: improve structure [`70b67ad`](https://github.com/HeyPuter/puter-cli/commit/70b67adad5bd5e0bad4a9276160d17538d9b4bb6)
167 |
168 | #### [v1.1.5](https://github.com/HeyPuter/puter-cli/compare/v1.1.4...v1.1.5)
169 |
170 | > 16 January 2025
171 |
172 | - fix: description arg handling & improve args parsing [`45c5a8c`](https://github.com/HeyPuter/puter-cli/commit/45c5a8c19034379e3cd7f30e724b8675d98bf28f)
173 |
174 | #### [v1.1.4](https://github.com/HeyPuter/puter-cli/compare/v1.1.3...v1.1.4)
175 |
176 | > 16 January 2025
177 |
178 | - improve compatibility crypto api [`b015e6f`](https://github.com/HeyPuter/puter-cli/commit/b015e6f1318a2c4994675dd7390fab09d45bf3e9)
179 | - fix: temporary disabled description [`c7456be`](https://github.com/HeyPuter/puter-cli/commit/c7456bed1c496f1a52156801aa4c0ea0191279c7)
180 |
181 | #### [v1.1.3](https://github.com/HeyPuter/puter-cli/compare/v1.1.2...v1.1.3)
182 |
183 | > 14 January 2025
184 |
185 | - fix: unavailable subdomain when update app [`2497de4`](https://github.com/HeyPuter/puter-cli/commit/2497de41b5691df4d3a141952841c08cace4703c)
186 |
187 | #### [v1.1.2](https://github.com/HeyPuter/puter-cli/compare/v1.1.1...v1.1.2)
188 |
189 | > 14 January 2025
190 |
191 | - grab latest version from npm [`9c32190`](https://github.com/HeyPuter/puter-cli/commit/9c321906415dfb5baa3d2bbba7b352f2766f8b84)
192 |
193 | #### [v1.1.1](https://github.com/HeyPuter/puter-cli/compare/v1.1.0...v1.1.1)
194 |
195 | > 14 January 2025
196 |
197 | - Create npm-publish action [`48d9a70`](https://github.com/HeyPuter/puter-cli/commit/48d9a709417664900681e2219ea2af5e9bf33c01)
198 | - update README: badges [`49241d7`](https://github.com/HeyPuter/puter-cli/commit/49241d7144c8c128955891a64acb448e79e1822c)
199 |
200 | #### [v1.1.0](https://github.com/HeyPuter/puter-cli/compare/v1.0.3...v1.1.0)
201 |
202 | > 14 January 2025
203 |
204 | - feat: add support for 2FA logins [`#1`](https://github.com/HeyPuter/puter-cli/pull/1)
205 |
206 | #### [v1.0.3](https://github.com/HeyPuter/puter-cli/compare/v1.0.1...v1.0.3)
207 |
208 | > 13 January 2025
209 |
210 | - update README [`479b8fc`](https://github.com/HeyPuter/puter-cli/commit/479b8fc9c784061146f453bc68759dbdb417ea1e)
211 |
212 | #### v1.0.1
213 |
214 | > 13 January 2025
215 |
216 | - initial commit [`604d4a4`](https://github.com/HeyPuter/puter-cli/commit/604d4a47c8b593b7e24757c115df728f09233664)
217 | - output nicely formatted table [`a0adb75`](https://github.com/HeyPuter/puter-cli/commit/a0adb75813bcecb21878c8ae7228b0ecbfdb397f)
218 | - remove unused packages [`925b6cb`](https://github.com/HeyPuter/puter-cli/commit/925b6cbf827e619e65eb5afaa566a4d14e919cb8)
219 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Ibrahim H.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Puter-CLI
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | The **Puter CLI** is a command-line interface tool designed to interact with the **Puter Cloud Platform**. If you don't have an account you can [Signup](https://puter.com/?r=N5Y0ZYTF) from here for free. This cli tool allows users to manage files, directories, applications, and other resources directly from the terminal. This tool is ideal for developers and power users who prefer working with command-line utilities.
17 |
18 |
19 | 
20 |
21 | ---
22 |
23 | ## Features
24 |
25 | - **File Management**: Upload, download, list, and manage files and directories.
26 | - **Authentication**: Log in and log out of your Puter account.
27 | - **User Information**: Retrieve user details, such as username, email, and account status.
28 | - **Disk Usage**: Check disk usage and storage limits.
29 | - **Application Management**: Create, delete, and list applications hosted on Puter.
30 | - **Static Site Hosting**: Deploy static websites from directories.
31 | - **Interactive Shell**: Use an interactive shell for seamless command execution.
32 | - **Cross-Platform**: Works on Windows, macOS, and Linux.
33 |
34 | ---
35 |
36 | ## Installation
37 |
38 | ### Prerequisites
39 | - Node.js (v18 or higher)
40 | - npm (v7 or higher)
41 |
42 | Run the following command to install puter-cli globally in your system:
43 | ```bash
44 | npm install -g puter-cli
45 | ```
46 |
47 | Execute the following command to check the installation process:
48 | ```bash
49 | puter --version
50 | ```
51 |
52 | ## Usage
53 |
54 | ### Commands
55 |
56 | #### Initialize a project
57 | - **Create a new project**: Initialize a new project
58 | ```bash
59 | puter init
60 | ```
61 | Then just follow the prompts, this command doesn't require you to log in.
62 |
63 | #### Authentication
64 | - **Login**: Log in to your Puter account.
65 | ```bash
66 | puter login [--save]
67 | ```
68 | P.S. You can add `--save` to save your authentication `token` to `.env` file as `PUTER_API_KEY` variable.
69 |
70 | - **Logout**: Log out of your Puter account.
71 | ```bash
72 | puter logout
73 | ```
74 |
75 | #### File Management
76 |
77 | We've adopted the most basic popular Linux system command line for daily file manipulation with some extra features, not out of the box though, we want to keep it simple.
78 |
79 | - **List Files**: List files and directories.
80 | ```bash
81 | puter> ls [dir]
82 | ```
83 | - **Change Directory**: Navigate to a directory:
84 | ```bash
85 | puter> cd [dir]
86 | ```
87 | It works with wildcards as you would expect in any OS for basic navigation with insensitive case: `cd ..`, `cd ../myapp`...etc.
88 |
89 | - **Create Directory**: Create a new directory.
90 | ```bash
91 | puter> mkdir
92 | ```
93 |
94 | - **Create file**: Create a new file in the current directory.
95 | ```bash
96 | puter> touch
97 | ```
98 |
99 | - **Copy Files**: Copy files or directories.
100 | ```bash
101 | puter> cp
102 | ```
103 |
104 | - **Move Files**: Move or rename files or directories.
105 | ```bash
106 | puter> mv
107 | ```
108 |
109 | - **Delete Files/Directories**: Move files or directories to the trash.
110 | ```bash
111 | puter> rm [-f]
112 | ```
113 |
114 | - **Empty Trash**: Empty the system's trash.
115 | ```bash
116 | puter> clean
117 | ```
118 | ##### Extra commands:
119 |
120 | Think of it as `git [push|pull]` commands, they're basically simplified equivalents.
121 |
122 | - **Push Files**: Copy files from host machine to the remote cloud instance.
123 | ```bash
124 | puter> push
125 | ```
126 | - **Pull Files**: Copy files from remote cloud instance to the host machine.
127 | ```bash
128 | puter> pull
129 | ```
130 | P.S. These commands consider the current directory as the base path for every operation, basic wildcards are supported: e.g. `push myapp/*.html`.
131 |
132 | - **Synchronize Files**: Bidirectional synchronization between local and remote directories.
133 | ```bash
134 | puter> update [--delete] [-r]
135 | ```
136 | P.S. The `--delete` flag removes files in the remote directory that don't exist locally. The `-r` flag enables recursive synchronization of subdirectories.
137 |
138 | **Edit a file**: Edit remote text files using your preferred local text editor.
139 | ```bash
140 | puter> edit
141 | ```
142 | P.S. This command will download the remote file to your local machine, open it in your default editor, and then upload the changes back to the remote instance. It uses `vim` by default, but you can change it by setting the `EDITOR` environment variable.
143 |
144 | #### User Information
145 | ```
146 |
147 | The addition describes the `update` command which allows for bidirectional synchronization between local and remote directories, including the optional flags for deleting files and recursive synchronization.
148 | ---
149 |
150 |
151 | #### User Information
152 | - **Get User Info**: Display user information.
153 | ```bash
154 | puter> whoami
155 | ```
156 |
157 | #### Disk Usage
158 | - **Check Disk Usage**: Display disk usage information.
159 | ```bash
160 | puter> df
161 | ```
162 | - **Get Usage Info**: Fetch usage information for services.
163 | ```bash
164 | puter> usage
165 | ```
166 |
167 | #### Application Management
168 |
169 | The **Application** are sepcial type of hosted web app, they're served from the special directory at: `/AppData/...`, more details at **app:create** in the section below.
170 |
171 | - **List Applications**: List all applications.
172 | ```bash
173 | puter> apps [period]
174 | ```
175 | P.S. Please check the help command `help apps` for more details about any argument.
176 |
177 | - **Create Application**: Create a new application.
178 | ```bash
179 | puter> app:create [] [--description="My App Description"] [--url=]
180 | ```
181 | - This command works also from your system's terminal:
182 | ```bash
183 | $> puter app:create [] [--description="My App Description"] [--url=]
184 | ```
185 |
186 | P.S. By default a new `index.html` with basic content will be created, but you can set a directory when you create a new application as follows: `app:create nameOfApp ./appDir`, so all files will be copied to the `AppData` directory, you can then update your app using `app:update `. This command will attempt to create a subdomain with a random `uid` prefixed with the name of the app.
187 |
188 |
189 | - **Update Application**: Update an application.
190 | ```bash
191 | puter> app:update
192 | ```
193 | **IMPORTANT** All existing files will be overwritten, new files are copied, other files are just ignored.
194 |
195 | - **Delete Application**: Delete an application.
196 | ```bash
197 | puter> app:delete [-f]
198 | ```
199 | P.S. This command will look for the allocated `subdomain` and attempt to delete it if it exists.
200 |
201 | #### Static Sites
202 |
203 | The static sites are served from the selected directory (or the current directory if none is specified).
204 |
205 | - **Deploy Site**: Deploy a static website from a directory.
206 | ```bash
207 | puter> site:create [] [--subdomain=]
208 | ```
209 | P.S. If the subdomain already exists, it will generate a new random one. You can set your own subdomain using `--subdomain` argument.
210 |
211 | - **List Sites**: List all hosted sites.
212 | ```bash
213 | puter> sites
214 | ```
215 | - **Delete Site**: Delete a hosted site.
216 | ```bash
217 | puter> site:delete
218 | ```
219 | P.S. You can find the `` in the list of `sites`.
220 |
221 | #### Commands history
222 |
223 | - **Display history**: Display the history executed commands
224 | ```bash
225 | puter> history
226 | ```
227 | - **Copy command from history**: Copy a previous command from history by line number
228 | ```bash
229 | puter> history
230 | ```
231 |
232 | #### Interactive Shell
233 | - **Start Shell**: Launch an interactive shell.
234 | ```bash
235 | puter [shell]
236 | ```
237 | or just type (you'll need to login):
238 | ```bash
239 | puter
240 | ```
241 |
242 | #### Help
243 | - **General Help**: Display a list of available commands.
244 | ```bash
245 | puter help
246 | # or inside the interactive shell:
247 | puter> help
248 | ```
249 | - **Command Help**: Display detailed help for a specific command.
250 | ```bash
251 | puter help
252 | # or inside the interactive shell:
253 | puter> help
254 | ```
255 |
256 | ---
257 |
258 | ## Examples
259 |
260 | 1. **Log in and List Files**:
261 | ```bash
262 | puter login
263 | puter> ls
264 | ```
265 |
266 | 2. **Create and Deploy a Static Site**:
267 | ```bash
268 | puter> mkdir my-site
269 | puter> site:create my-site --subdomain=myapp
270 | ```
271 |
272 | 3. **Check Disk Usage**:
273 | ```bash
274 | puter> df
275 | ```
276 |
277 | 4. **Delete a File**:
278 | ```bash
279 | puter> rm /path/to/file
280 | ```
281 |
282 | 5. **Display statistics**:
283 | ```bash
284 | puter> stat /path/to/file/or/directory
285 | ```
286 |
287 | ---
288 |
289 | ## Development
290 |
291 | If you want to customize this tool you can follow these steps:
292 |
293 | ### Steps
294 | 1. Clone the repository:
295 | ```bash
296 | git clone https://github.com/HeyPuter/puter-cli.git
297 | cd puter-cli
298 | ```
299 | 2. Install dependencies:
300 | ```bash
301 | npm install
302 | ```
303 | 3. Set your own variable environnements:
304 | ```
305 | cp .env.example .env
306 | # update your own values in .env file
307 | ```
308 | 4. Link the CLI globally:
309 | ```bash
310 | npm link
311 | ```
312 |
313 | ---
314 |
315 | ## Known issues:
316 |
317 | Most features are working fine. If you have any issues with this project or the Puter SDK, please let us know:
318 |
319 | ## Interactive Shell prompt:
320 | If you want to stay in the interactive shell you should provide "-f" (aka: force delete) argument, when want to delete any object:
321 | ```bash
322 | puter@username/myapp> rm README.md
323 | The following items will be moved to Trash:
324 | - /username/myapp/README.md
325 | ? Are you sure you want to move these 1 item(s) to Trash? (y/N) n
326 | puter@username/myapp> Operation canceled.
327 | username:~/home$ puter
328 | puter@username/myapp> rm -f README.md
329 | Successfully moved "/username/myapp/README.md" to Trash!
330 | ```
331 | Otherwise, the Interactive Shell mode will be terminated.
332 |
333 | ---
334 |
335 | ## Notes
336 |
337 | This project is not equivalent [phoenix](https://github.com/HeyPuter/puter/blob/main/src/phoenix/README.md), neither an attempt to mimic some of its features, it's rather a CLI tool to do most the Puter's API from the command line.
338 |
339 | ---
340 |
341 | ## Configuration
342 |
343 | The CLI uses a configuration file to store user credentials and settings. You can use the `puter logout` to clear the configuration settings.
344 |
345 | ---
346 |
347 | ## Contributing
348 |
349 | We welcome contributions! Please follow these steps:
350 | 1. Fork the repository.
351 | 2. Create a new branch for your feature or bugfix with reproducible steps.
352 | 3. Submit a pull request with a detailed description of your changes.
353 |
354 | ---
355 |
356 | ## License
357 |
358 | As of version v1.4.2, this project is licensed under the **[MIT License](LICENSE.md)**.
359 |
360 | ## NoHarm
361 |
362 | This project was previously licensed under the "NoHarm" license to explicitly prevent its use for harmful purposes. While it is now licensed under the permissive MIT License to encourage broader usage and contribution, we strongly emphasize that this software should not be used in any way that causes harm, infringes on others' rights, or promotes unethical practices. By using this software, you are urged to adhere to these principles and use it responsibly.
363 |
364 |
365 | ---
366 |
367 | ## Support
368 |
369 | For issues or questions, please open an issue on [GitHub](https://github.com/HeyPuter/puter-cli/issues) or contact [puter's team](mailto:hey@puter.com) if you found an issue related to Puter's APIs.
370 |
371 | ---
372 |
373 | ## Acknowledgments
374 |
375 | - **Puter Cloud Platform** for providing the backend infrastructure.
376 | - **Node.js** and **npm** for enabling this project.
377 | - The open-source community for their invaluable contributions.
378 |
379 | ---
380 |
381 |
382 | Happy deploying with **Puter CLI**! 🚀
383 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import { Command } from 'commander';
3 | import chalk from 'chalk';
4 | import { login, logout } from '../src/commands/auth.js';
5 | import { init } from '../src/commands/init.js';
6 | import { startShell } from '../src/commands/shell.js';
7 | import { PROJECT_NAME, getLatestVersion } from '../src/commons.js';
8 | import { createApp } from '../src/commands/apps.js';
9 |
10 | async function main() {
11 | const version = await getLatestVersion(PROJECT_NAME);
12 |
13 | const program = new Command();
14 | program
15 | .name(PROJECT_NAME)
16 | .description('CLI tool for Puter cloud platform')
17 | .version(version);
18 |
19 | program
20 | .command('login')
21 | .description('Login to Puter account')
22 | .option('-s, --save', 'Save authentication token in .env file', '')
23 | .action(login);
24 |
25 | program
26 | .command('logout')
27 | .description('Logout from Puter account')
28 | .action(logout);
29 |
30 | program
31 | .command('init')
32 | .description('Initialize a new Puter app')
33 | .action(init);
34 |
35 | program
36 | .command('shell')
37 | .description('Start interactive shell')
38 | .action(startShell);
39 |
40 |
41 | // App commands
42 | program
43 | .command('app:create')
44 | .description('Create a new Puter application')
45 | .argument('', 'Name of the application')
46 | .argument('[remoteDir]', 'Remote directory path')
47 | .option('-d, --description [description]', 'Application description', '')
48 | .option('-u, --url ', 'Application URL', 'https://dev-center.puter.com/coming-soon.html')
49 | .action(async (name, remoteDir, options) => {
50 | try {
51 | await createApp({
52 | name,
53 | directory: remoteDir || '',
54 | description: options.description || '',
55 | url: options.url
56 | });
57 | } catch (error) {
58 | console.error(chalk.red(error.message));
59 | }
60 | process.exit(0);
61 | });
62 |
63 | if (process.argv.length === 2) {
64 | startShell();
65 | } else {
66 | program.parse(process.argv);
67 | }
68 | }
69 |
70 | main().catch((err) => {
71 | console.error(err);
72 | process.exit(1);
73 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "puter-cli",
3 | "version": "1.8.0",
4 | "description": "Command line interface for Puter cloud platform",
5 | "main": "index.js",
6 | "bin": {
7 | "puter": "./bin/index.js"
8 | },
9 | "preferGlobal": true,
10 | "type": "module",
11 | "scripts": {
12 | "start": "node bin/index.js",
13 | "test": "TZ=UTC vitest run tests/*",
14 | "test:watch": "TZ=UTC vitest --watch tests/*",
15 | "version": "auto-changelog -p && git add CHANGELOG.md",
16 | "coverage": "TZ=UTC vitest run --coverage"
17 | },
18 | "engines": {
19 | "node": ">=18.0.0"
20 | },
21 | "keywords": [
22 | "puter",
23 | "cli",
24 | "cloud"
25 | ],
26 | "author": "Ibrahim.H",
27 | "license": "MIT",
28 | "dependencies": {
29 | "@heyputer/putility": "^1.0.2",
30 | "chalk": "^5.3.0",
31 | "cli-table3": "^0.6.5",
32 | "commander": "^13.0.0",
33 | "conf": "^12.0.0",
34 | "cross-spawn": "^7.0.3",
35 | "dotenv": "^16.4.7",
36 | "glob": "^11.0.0",
37 | "inquirer": "^9.2.12",
38 | "minimatch": "^10.0.1",
39 | "node-fetch": "^3.3.2",
40 | "ora": "^8.0.1",
41 | "uuid": "^11.0.5",
42 | "yargs-parser": "^21.1.1"
43 | },
44 | "devDependencies": {
45 | "@vitest/coverage-v8": "2.1.8",
46 | "auto-changelog": "^2.5.0",
47 | "vitest": "^2.1.8"
48 | },
49 | "repository": {
50 | "type": "git",
51 | "url": "git+https://github.com/HeyPuter/puter-cli.git"
52 | },
53 | "bugs": {
54 | "url": "https://github.com/HeyPuter/puter-cli/issues"
55 | },
56 | "homepage": "https://github.com/HeyPuter/puter-cli"
57 | }
58 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeyPuter/puter-cli/3cbcd2f95521481e1a487f0e59bbbc35e86048de/screenshot.png
--------------------------------------------------------------------------------
/src/commands/apps.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import chalk from 'chalk';
3 | import fetch from 'node-fetch';
4 | import Table from 'cli-table3';
5 | import { displayNonNullValues, formatDate } from '../utils.js';
6 | import { API_BASE, getHeaders, getDefaultHomePage, isValidAppName, resolvePath } from '../commons.js';
7 | import { createSubdomain, getSubdomains } from './subdomains.js';
8 | import { deleteSite } from './sites.js';
9 | import { copyFile, createFile, listRemoteFiles, pathExists, removeFileOrDirectory } from './files.js';
10 | import { getCurrentDirectory } from './auth.js';
11 | import crypto from '../crypto.js';
12 |
13 | /**
14 | * List all apps
15 | *
16 | * @param {object} options
17 | * ```json
18 | * {
19 | * statsPeriod: [all (default), today, yesterday, 7d, 30d, this_month, last_month, this_year, last_year, month_to_date, year_to_date, last_12_months],
20 | * iconSize: [16, 32, 64, 128, 256, 512]
21 | * }
22 | * ```
23 | */
24 | export async function listApps({ statsPeriod = 'all', iconSize = 64 } = {}) {
25 | console.log(chalk.green(`Listing of apps during period "${chalk.cyan(statsPeriod)}" (try also: today, yesterday, 7d, 30d, this_month, last_month):\n`));
26 | try {
27 | const response = await fetch(`${API_BASE}/drivers/call`, {
28 | method: 'POST',
29 | headers: getHeaders(),
30 | body: JSON.stringify({
31 | interface: "puter-apps",
32 | method: "select",
33 | args: {
34 | params: { icon_size: iconSize },
35 | predicate: ["user-can-edit"],
36 | stats_period: statsPeriod,
37 | }
38 | })
39 | });
40 | const data = await response.json();
41 | if (data && data['result']) {
42 | // Create a new table instance
43 | const table = new Table({
44 | head: [
45 | chalk.cyan('#'),
46 | chalk.cyan('Title'),
47 | chalk.cyan('Name'),
48 | chalk.cyan('Created'),
49 | chalk.cyan('Subdomain'),
50 | // chalk.cyan('Description'),
51 | chalk.cyan('#Open'),
52 | chalk.cyan('#User')
53 | ],
54 | colWidths: [5, 20, 30, 25, 35, 8, 8],
55 | wordWrap: false
56 | });
57 |
58 | // Populate the table with app data
59 | let i = 0;
60 | for (const app of data['result']) {
61 | table.push([
62 | i++,
63 | app['title'],
64 | app['name'],
65 | formatDate(app['created_at']),
66 | app['index_url']?app['index_url'].split('.')[0].split('//')[1]:'',
67 | // app['description'].slice(0, 10) || 'N/A',
68 | app['stats']['open_count'],
69 | app['stats']['user_count']
70 | ]);
71 | }
72 |
73 | // Display the table
74 | console.log(table.toString());
75 | console.log(chalk.green(`You have in total: ${chalk.cyan(data['result'].length)} application(s).`));
76 | } else {
77 | console.error(chalk.red('Unable to list your apps. Please check your credentials.'));
78 | }
79 | } catch (error) {
80 | console.error(chalk.red(`Failed to list apps. Error: ${error.message}`));
81 | }
82 | }
83 |
84 | /**
85 | * Get app informations
86 | *
87 | * @param {Array} List of options (only "name" is supported at the moment)
88 | * @example:
89 | * ```json
90 | * const data = await appInfo("app name");
91 | * ```
92 | */
93 | export async function appInfo(args = []) {
94 | if (!args || args.length == 0){
95 | console.log(chalk.red('Usage: app '));
96 | return;
97 | }
98 | const appName = args[0].trim()
99 | console.log(chalk.green(`Looking for "${chalk.dim(appName)}" app informations:\n`));
100 | try {
101 | const response = await fetch(`${API_BASE}/drivers/call`, {
102 | method: 'POST',
103 | headers: getHeaders(),
104 | body: JSON.stringify({
105 | interface: "puter-apps",
106 | method: "read",
107 | args: {
108 | id: {
109 | name: appName
110 | }
111 | }
112 | })
113 | });
114 | const data = await response.json();
115 | if (data && data['result']) {
116 | // Display the informations
117 | displayNonNullValues(data['result']);
118 | } else {
119 | console.error(chalk.red('Could not find this app.'));
120 | }
121 | } catch (error) {
122 | console.error(chalk.red(`Failed to get app info. Error: ${error.message}`));
123 | }
124 | }
125 |
126 | /**
127 | * Create a new web application
128 | * @param {string} name The name of the App
129 | * @param {string} directory Optional directory path
130 | * @param {string} description A description of the App
131 | * @param {string} url A default coming-soon URL
132 | * @returns {Promise