Upload AGENTS.md with huggingface_hub
Browse files
AGENTS.md
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Development Guide for Pinokio Projects
|
| 2 |
+
|
| 3 |
+
## Non-Negotiable Execution Workflow
|
| 4 |
+
|
| 5 |
+
To guarantee every contribution follows this guide precisely, obey this checklist **before any edits** and **again before finalizing**. Do not skip or reorder.
|
| 6 |
+
1. **AGENTS Snapshot:** Re-open this file and write down (in your working notes or response draft) the exact sections relevant to the requested task. No work begins until this snapshot exists.
|
| 7 |
+
2. **Example Lock-in:** Identify the closest matching script in `C:\pinokio\prototype\system\examples`. Record its path and keep it open while editing. Every launcher change must mirror that reference unless the user explicitly instructs otherwise.
|
| 8 |
+
3. **Pre-flight Checklist:** Convert the applicable rules from this document and `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md into a task-specific checklist (install/start/reset/update structure, regex patterns, menu defaults, log checks, etc.). Confirm each item is ticked **before** making changes.
|
| 9 |
+
4. **Mid-task Verification:** Any time you touch a Pinokio script, cross-check the corresponding example line to ensure syntax and structure match. Document the reference (example path + line) in your reasoning.
|
| 10 |
+
5. **Exit Checklist:** Before responding to the user, revisit the pre-flight checklist and explicitly confirm every item is satisfied. If anything diverges from the example or these rules, fix it first.
|
| 11 |
+
|
| 12 |
+
If any step cannot be completed, stop immediately and ask the user how to proceed. These five steps are mandatory for every session.
|
| 13 |
+
|
| 14 |
+
### Critical Pattern Lock: Capturing Web UI URLs
|
| 15 |
+
|
| 16 |
+
When writing `start.js` (or any script that needs to surface a web URL for a server):
|
| 17 |
+
|
| 18 |
+
1. **Always copy the capture block from an example such as `system/examples/mochi/start.js`.**
|
| 19 |
+
```javascript
|
| 20 |
+
on: [{
|
| 21 |
+
event: "/(http:\\/\\/[0-9.:]+)/",
|
| 22 |
+
done: true
|
| 23 |
+
}]
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
2. **Set the local variable using the captured match exactly as below (The regex capture object is passed in as `input.event`, so need to use the index 1 inside the parenthesis):**
|
| 27 |
+
```javascript
|
| 28 |
+
{
|
| 29 |
+
method: "local.set",
|
| 30 |
+
params: {
|
| 31 |
+
url: "{{input.event[1]}}"
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
3. Always try to come up with the most generic regex.
|
| 37 |
+
4. During the exit checklist, explicitly confirm that the `url` local variable is set via `local.set` API by using the captured regex object as passed in as `input.event` from the previous `shell.run` step.
|
| 38 |
+
|
| 39 |
+
Deviation from this pattern requires written approval from the user.
|
| 40 |
+
|
| 41 |
+
- Make sure to keep this entire document and `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md in memory with high priority before making any decision. Pinokio is a system that makes it easy to write launchers through scripting by providing various cross-platform APIs, so whenever possible you should prioritize using Pinokio API over lower level APIs.
|
| 42 |
+
- When writing pinokio scripts, ALWAYS check the examples folder (in C:\pinokio\prototype\system\examples folder) to see if there are existing example scripts you can imitate, instead of assuming syntax.
|
| 43 |
+
- When implementing pinokio script APIs and you cannot infer the syntax just based on the examples, always search the API documentation `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md to use the correct syntax instead of assuming the syntax.
|
| 44 |
+
- When trying to fix something or figure out what's going on, ALWAYS start by checking the `logs` folder before doing anything else, as mentioned in the "Troubleshooting with Logs" section.
|
| 45 |
+
- Finally, make sure to ALWAYS follow all the items in the "best practices" section below.
|
| 46 |
+
|
| 47 |
+
## Determine User Intent
|
| 48 |
+
If the initial prompt is simply a URL and nothing else, check the website content and determine the intent, and ask the user to confirm. For example a URL may point to
|
| 49 |
+
|
| 50 |
+
1. A Tutorial: the intent may be to implement a demo for the tutorial and build a launcher.
|
| 51 |
+
2. A Demo: the intent may be a 1-click launcher for the demo
|
| 52 |
+
3. Open source project: the intent may be a 1-click launcher for the project
|
| 53 |
+
4. Regular website: the intent may be to clone the website and a launcher.
|
| 54 |
+
5. There can be other cases, but try to guess.
|
| 55 |
+
|
| 56 |
+
## Project Structure
|
| 57 |
+
|
| 58 |
+
Pinokio projects normally follow a standardized structure with app logic separated from launcher scripts:
|
| 59 |
+
|
| 60 |
+
Pinokio projects follow a standardized structure with app logic separated from launcher scripts:
|
| 61 |
+
|
| 62 |
+
```
|
| 63 |
+
project-root/
|
| 64 |
+
βββ app/ # Self-contained app logic (can be standalone repo)
|
| 65 |
+
β βββ package.json # Node.js projects
|
| 66 |
+
β βββ requirements.txt # Python projects
|
| 67 |
+
β βββ ... # Other language-specific files
|
| 68 |
+
βββ README.md # Documentation
|
| 69 |
+
βββ install.js # Installation script
|
| 70 |
+
βββ start.js # Launch script
|
| 71 |
+
βββ update.js # Update script (for updating the scripts and app logic to the latest)
|
| 72 |
+
βββ reset.js # Reset dependencies script
|
| 73 |
+
βββ pinokio.js # UI generator script
|
| 74 |
+
βββ pinokio.json # Metadata (title, description, icon)
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
- Keep app code in `/app` folder only (never in root)
|
| 78 |
+
- Store all launcher files in project root (never in `/app`)
|
| 79 |
+
- `/app` folder should be self-contained and publishable
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
The only exceptions are serverless web apps---purely frontend only web applications that do NOT have a server component and connect to 3rd party API endpoints--in which case the folder structure looks like the following (No need for launcher scripts since the index.html will automatically launch. The only thing needed is the metadata file named pinokio.json):
|
| 83 |
+
|
| 84 |
+
```
|
| 85 |
+
project-root/
|
| 86 |
+
βββ index.html # The serverless web app entry point
|
| 87 |
+
βββ ...
|
| 88 |
+
βββ README.md # Documentation
|
| 89 |
+
βββ pinokio.json # Metadata (title, description, icon)
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
IMPORTANT: ALWAYS try to follow the best practices in the examples folder (C:\pinokio\prototype\system\examples) instead of trying to come up with your own structure. The examples have been optimized for the best user experience.
|
| 93 |
+
|
| 94 |
+
## Launcher Project Working Directory
|
| 95 |
+
|
| 96 |
+
- The project working directory for a script is always the same directory as the script location.
|
| 97 |
+
- For example, when you run `shell.run` API inside `pinokio/start.js`, the default path for shell execution is `pinokio`.
|
| 98 |
+
- If the launcher files are in the project root path, then the default path for shell execution is the project root.
|
| 99 |
+
- Therefore, it is important to specify the correct `path` attribute when running `shell.run` API commands.
|
| 100 |
+
|
| 101 |
+
Example: in the following project structure:
|
| 102 |
+
|
| 103 |
+
```
|
| 104 |
+
project-root/
|
| 105 |
+
βββ pinokio/ # Pinokio launcher folder
|
| 106 |
+
β βββ start.js # Launch script
|
| 107 |
+
β βββ pinokio.js # UI generator script
|
| 108 |
+
β βββ pinokio.json # Metadata (title, description, icon)
|
| 109 |
+
ββββ backend/
|
| 110 |
+
βββ requirements.txt # App dependencies
|
| 111 |
+
βββ app.py # App code
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
The `pinokio/start.js` should use the correct path `../backend` as the `path` attribute, as follows:
|
| 115 |
+
|
| 116 |
+
```
|
| 117 |
+
{
|
| 118 |
+
run: [{
|
| 119 |
+
...
|
| 120 |
+
}, {
|
| 121 |
+
method: "shell.run",
|
| 122 |
+
params: {
|
| 123 |
+
message: "python app.py",
|
| 124 |
+
venv: "env",
|
| 125 |
+
path: "../backend"
|
| 126 |
+
}
|
| 127 |
+
}, {
|
| 128 |
+
...
|
| 129 |
+
}]
|
| 130 |
+
}
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
## Development Workflow
|
| 134 |
+
|
| 135 |
+
### 1. Understanding the Project
|
| 136 |
+
- Check `SPEC.md` in project root. If the file exists, use that to learn about the project details (what and how to build)
|
| 137 |
+
- If no `SPEC.md` exists, build based on user requirements
|
| 138 |
+
### 2. Modifying Existing Launcher Projects
|
| 139 |
+
If we are starting with existing launcher script files, work with the existing files instead of coming up with your own.
|
| 140 |
+
- **Preserve existing functionality:** Only modify necessary parts
|
| 141 |
+
- **Don't touch working scripts:** Unless adding/updating specific commands
|
| 142 |
+
- **Follow existing conventions:** Match the style and structure already present
|
| 143 |
+
### 3. Try to adopt from examples as much as possible
|
| 144 |
+
- If starting from scratch, first determine what type of project you will be building, and then check the examples folder (C:\pinokio\prototype\system\examples) to see if you can adopt them instead of coming up everything from scratch.
|
| 145 |
+
- Even if there are no relevant examples, check the examples to get inspiration for how you would structure the script files even if you have to write from scratch.
|
| 146 |
+
### 4. Writing from scratch as a last resort
|
| 147 |
+
If there are relevant examples to adopt from, write the scripts from scratch, but just make sure to follow the requirements in the next section.
|
| 148 |
+
### 5. Debugging
|
| 149 |
+
When the user reports something is not working, ALWAYS inspect the logs folder to get all the execution logs. For more info on how this works, check the "Troubleshooting with Logs" section below.
|
| 150 |
+
|
| 151 |
+
## Script Requirements
|
| 152 |
+
|
| 153 |
+
### 1. 1-click launchable
|
| 154 |
+
- The main purpose of Pinokio is to provide an easy interface to invoke commands, which may include launching servers, installing programs, etc. Make sure the final product provides ways to install, launch, reset, and update whatever is needed.
|
| 155 |
+
|
| 156 |
+
### 2. Write Documentation
|
| 157 |
+
- ALWAYS write a documentation. A documentation must be stored as `README.md` in the project root folder, along with the rest of the pinokio launcher script files. A documentation file must contain:
|
| 158 |
+
- What the app does
|
| 159 |
+
- How to use the app
|
| 160 |
+
- API documentation for programmatically accessing the app's main features (Javascript, Python, and Curl)
|
| 161 |
+
|
| 162 |
+
## Types of launchers
|
| 163 |
+
## 1. Launching servers
|
| 164 |
+
- When an app requires launching a server, here are the commonly used scripts:
|
| 165 |
+
- `install.js`: a script to install the app
|
| 166 |
+
- `start.js`: a script to start the app
|
| 167 |
+
- `reset.js`: a script to reset all the dependencies installed in the `install.js` step. used if the user wants to restart from scratch
|
| 168 |
+
- `update.js`: a script to update the launcher AND the app in case there are new updates. Involves pulling in the relevant git repositories installed through `install.js` (often it's the script repo and some git repositories cloned through the install steps if any)
|
| 169 |
+
- `pinokio.js`: the launcher script that ties all of the above scripts together by providing a UI that links to these scripts.
|
| 170 |
+
- `pinokio.json`: For metadata
|
| 171 |
+
|
| 172 |
+
Here's a basic server launcher script example (`start.js`). Unless there's a special reason you need to use another pattern, this is the most recommended pattern. Use this or adopt it as needed, but NEVER try something else unless there's a good reason you should not take this approach:
|
| 173 |
+
|
| 174 |
+
```javascript
|
| 175 |
+
module.exports = {
|
| 176 |
+
// By setting daemon: true, the script keeps running even after all items in the `run` array finishes running. Mandatory for launching servers, since otherwise the shells running the server process will get killed after the scripts finish running.
|
| 177 |
+
daemon: true,
|
| 178 |
+
run: [
|
| 179 |
+
{
|
| 180 |
+
// The "shell.run" API for running a shell session
|
| 181 |
+
method: "shell.run",
|
| 182 |
+
params: {
|
| 183 |
+
// Edit 'venv' to customize the venv folder path
|
| 184 |
+
venv: "env",
|
| 185 |
+
// Edit 'env' to customize environment variables (see documentation)
|
| 186 |
+
env: { },
|
| 187 |
+
// Edit 'path' to customize the path to start the shell from
|
| 188 |
+
path: "app",
|
| 189 |
+
// Edit 'message' to customize the commands, or to run multiple commands
|
| 190 |
+
message: [
|
| 191 |
+
"python app.py",
|
| 192 |
+
],
|
| 193 |
+
on: [{
|
| 194 |
+
// The regular expression pattern to monitor.
|
| 195 |
+
// Whenever each "event" pattern occurs in the shell terminal, the shell will return,
|
| 196 |
+
// and the script will go onto the next step.
|
| 197 |
+
// The regular expression match object will be passed on to the next step as `input.event`
|
| 198 |
+
// Useful for capturing the URL at which the server is running (in case the server prints some message about where the server is running)
|
| 199 |
+
"event": "/(http:\/\/\\S+)/",
|
| 200 |
+
|
| 201 |
+
// Use "done": true to move to the next step while keeping the shell alive.
|
| 202 |
+
// Use "kill": true to move to the next step after killing the shell.
|
| 203 |
+
"done": true
|
| 204 |
+
}]
|
| 205 |
+
}
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
// This step sets the local variable 'url'.
|
| 209 |
+
// This local variable will be used in pinokio.js to display the "Open WebUI" tab when the value is set.
|
| 210 |
+
method: "local.set",
|
| 211 |
+
params: {
|
| 212 |
+
// the input.event is the regular expression match object from the previous step
|
| 213 |
+
// In this example, since the pattern was "/(http:\/\/\\S+)/", input.event[1] will include the exact http url match caputred by the parenthesis.
|
| 214 |
+
// Therefore setting the local variable 'url'
|
| 215 |
+
url: "{{input.event[1]}}"
|
| 216 |
+
}
|
| 217 |
+
}
|
| 218 |
+
]
|
| 219 |
+
}
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
## 2. Launching serverless web apps
|
| 223 |
+
|
| 224 |
+
- In case of purely static web apps WITHOUT servers or backends (for example an HTML based app that connects to 3rd party servers--either remote or localhost), we do NOT need the launcher scripts.
|
| 225 |
+
- In these cases, simply include `index.html` in the project root folder and everything should automatically work. No need for any of the pinokio launcher scripts. (Do
|
| 226 |
+
- You still need to include the metadata file so they show up properly on pinokio:
|
| 227 |
+
- `pinokio.json`: For metadata
|
| 228 |
+
|
| 229 |
+
## 3. Launching quick scripts without web UI
|
| 230 |
+
|
| 231 |
+
- In many cases, we may not even need a web UI, but instead just a simple way to run scripts.
|
| 232 |
+
- This may include TUI (Terminal User Interface) apps, a simple launcher
|
| 233 |
+
- In these cases, all we need is the launcher file `pinokio.js`, which may link to multiple scripts. In this case, there are no web apps (no serverless apsp, no servers), but instead just the default pinokio launcher UI that calls a bunch of scripts.
|
| 234 |
+
- Here are some examples:
|
| 235 |
+
- A pinokio script to toggle the desktop theme between dark and light
|
| 236 |
+
- Write some code (python or javascript or whatever)
|
| 237 |
+
- Write a `toggle.js` pinokio script that executes the code
|
| 238 |
+
- Write a `pinokio.js` launcher script to create a sidebar UI that displays the `toggle.js` so the user can simply click the "toggle" button to toggle back and forth between desktop themes
|
| 239 |
+
- A pinokio script to fetch some file
|
| 240 |
+
- Write some code (python or javascript or whatever)
|
| 241 |
+
- Write a `fetch.js` pinokio script that executes the code
|
| 242 |
+
- Write a `pinokio.js` launcher script to create a sidebar UI that displays the `fetch.js` so the user can simply click the "fetch" button to fetch some data.
|
| 243 |
+
- You still need to include the metadata file so they show up properly on pinokio:
|
| 244 |
+
- `pinokio.json`: For metadata
|
| 245 |
+
|
| 246 |
+
## API
|
| 247 |
+
|
| 248 |
+
This section lists all the script APIs available on Pinokio. To learn the details of how they are used, you can:
|
| 249 |
+
1. Check the examples in the C:\pinokio\prototype\system\examples folder
|
| 250 |
+
2. Read the `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md further documentation on the full syntax
|
| 251 |
+
|
| 252 |
+
### Script API
|
| 253 |
+
|
| 254 |
+
These APIs can be used to describe each step in a pinokio script:
|
| 255 |
+
- shell.run: run shell commands
|
| 256 |
+
- input: accept user input
|
| 257 |
+
- filepicker: accept file upload
|
| 258 |
+
- fs.write: write to file
|
| 259 |
+
- fs.read: read from file
|
| 260 |
+
- fs.copy: copy files
|
| 261 |
+
- fs.download: download files
|
| 262 |
+
- fs.link: create a symbolic link (or junction on windows) for folders
|
| 263 |
+
- fs.open: open the system file explorer at a given path
|
| 264 |
+
- fs.cat: print file contents
|
| 265 |
+
- jump: jump to a specific step
|
| 266 |
+
- local.set: set local variables for the currently running script
|
| 267 |
+
- json.set: update a json file
|
| 268 |
+
- json.rm: remove keys from a json file
|
| 269 |
+
- json.get: get values from a json file
|
| 270 |
+
- log: print to the web terminal
|
| 271 |
+
- net: make network requests
|
| 272 |
+
- notify: display a notification
|
| 273 |
+
- script.download: download a script from a git uri
|
| 274 |
+
- script.start: start a script
|
| 275 |
+
- script.stop: stop a script
|
| 276 |
+
- script.return: return values if the current script was called by a caller script, so the caller script can utilize the return value as `input`
|
| 277 |
+
- web.open: open a url in web browser
|
| 278 |
+
- hf.download: huggingfac-cli download API
|
| 279 |
+
### Template variables
|
| 280 |
+
The following variables are accessible inside template expressions (example `{{args.command}` in scripts, resulting in dynamic behaviors of scripts:
|
| 281 |
+
- input: An input is a variable that gets passed from one RPC call to the next
|
| 282 |
+
- args: args is the parameter object that gets passed into the script (via pinokio.js `params`). Unlike `input` which takes the value passed in from the immediately previous step, `args` is a global value that is the same through out the entire script execution.
|
| 283 |
+
- local: local variable object that can be set with `local.set` API
|
| 284 |
+
- self: refers to the script file itself (which is JSON or JavaScript). For example if `start.js` that's currently running has `daemon: true` set, `{{self.daemon}}` will evaluate to true.
|
| 285 |
+
- uri: The current script uri
|
| 286 |
+
- port: The next available port. Very useful when you need to launch an app at a specific port without port conflicts.
|
| 287 |
+
- cwd: The current script execution folder path
|
| 288 |
+
- platform: The current operating system. May be one of the following: `darwin`, `win32`, `linux`
|
| 289 |
+
- arch: The current system architecture. May be one of the following: x32, x64, arm, arm64, s390, s390x, mipsel, ia32, mips, ppc, ppc64
|
| 290 |
+
- gpus: array of available GPUs on the machine (example: `['apple']`, `['nvidia']`)
|
| 291 |
+
- gpu: the first available GPU (example: `nvidia`)
|
| 292 |
+
- current: The current variable points to the index of the currently executing instruction within the run array.
|
| 293 |
+
- next: The next variable points to the index of the next instruction to be executed. (null if the current instruction is the final instruction in the run array)
|
| 294 |
+
- envs: You can access the environment variables of the currently running process with envs object.
|
| 295 |
+
- which: Check whether a command exists (example: `{{which('winget')}}`. Can be used in the `when` attribute of a script step to run commands or install first.
|
| 296 |
+
- exists: Check whether a file or folder exists at the specified relative path (example: `"when": "{{!exists('app')}}"`). Can be used with the `when` attribute to determine a path's existence and trigger custom logic. Use relative paths and it will resolve automatically to the current execution folder.
|
| 297 |
+
- running: Check whether a script file is running (example: `"when": "{{!running('start.js')}}"`). Can be used with the `when` attribute to determine a path's existence and trigger custom logic. Use relative paths and it will resolve automatically to the current execution folder.
|
| 298 |
+
- os: Pinokio exposes the node.js os module through the os variable.
|
| 299 |
+
- path: Pinokio exposes the node.js path module through the os variable (example: `{{path.resolve(...)}}`
|
| 300 |
+
|
| 301 |
+
## System Capabilities
|
| 302 |
+
### Package Management (Use in Order of Preference)
|
| 303 |
+
The following package managers come pre-installed with Pinokio, so whenever you need to install a 3rd party binary, remember that these are available. Also, you can assume these are available and include the following package manager commands in Pinokio scripts:
|
| 304 |
+
1. **UV** - For Python packages (preferred over pip)
|
| 305 |
+
2. **NPM** - For Node.js packages
|
| 306 |
+
3. **Conda** - For cross-platform 3rd party binaries
|
| 307 |
+
4. **Brew** - Mac-only fallback when other options unavailable
|
| 308 |
+
5. **Git** - Full access to git is available.
|
| 309 |
+
**Important:** Include all install commands in the install script for reproducibility.
|
| 310 |
+
### HTTPS Proxy Support
|
| 311 |
+
- All HTTP servers automatically get HTTPS endpoints
|
| 312 |
+
- Convention: `http://localhost:<PORT>` β `https://<PORT>.localhost`
|
| 313 |
+
- Full proxy list available at: `http://localhost:2019/config/`
|
| 314 |
+
### Pterm Features:
|
| 315 |
+
- **Clipboard Access:** Read from or Write to system clipboard via pinokio Pterm CLI (`pterm clipboard` command.)
|
| 316 |
+
- **Notifications:** Send desktop alerts via pinokio pterm CLI (`pterm push` command.)
|
| 317 |
+
- **Script Testing:** Run launcher scripts via pinokio pterm CLI (`pterm start` command.)
|
| 318 |
+
- **File Selection:** Use built-in filepicker for user file/folder input (`pterm filepicker` command.)
|
| 319 |
+
- **Git Operations:** Clone repositories, push to GitHub
|
| 320 |
+
- **GitHub Integration:** Full GitHub CLI support (`gh` commands)
|
| 321 |
+
|
| 322 |
+
## Troubleshooting with Logs
|
| 323 |
+
Pinokio stores the logs for everything that happened in terminal at the following locations, so you can make use of them to determine what's going on:
|
| 324 |
+
|
| 325 |
+
### Log Structure
|
| 326 |
+
In case there is a `pinokio` folder in the project root folder, you should be able to find the logs folder here:
|
| 327 |
+
|
| 328 |
+
```
|
| 329 |
+
pinokio/
|
| 330 |
+
βββ logs/ # Direct user interaction logs
|
| 331 |
+
βββ api/ # Launcher script logs (install.js, start.js, etc.)
|
| 332 |
+
βββ dev/ # AI coding tool logs (organized by tool)
|
| 333 |
+
βββ shell/ # Direct user interaction logs
|
| 334 |
+
```
|
| 335 |
+
|
| 336 |
+
Otherwise, the `logs` folder should be found at project root:
|
| 337 |
+
|
| 338 |
+
```
|
| 339 |
+
logs/
|
| 340 |
+
βββ api/ # Launcher script logs (install.js, start.js, etc.)
|
| 341 |
+
βββ dev/ # AI coding tool logs (organized by tool)
|
| 342 |
+
βββ shell/ # Direct user interaction logs
|
| 343 |
+
```
|
| 344 |
+
|
| 345 |
+
### Log File Naming
|
| 346 |
+
- Unix timestamps for each session
|
| 347 |
+
- Special "latest" file contains most recent session logs
|
| 348 |
+
- **Default:** Use "latest" files for current issues
|
| 349 |
+
- **Historical:** Use timestamped files for pattern analysis and the full history.
|
| 350 |
+
|
| 351 |
+
## Best practices
|
| 352 |
+
### 0. Always reference the logs when debugging
|
| 353 |
+
- When the user asks to fix something, ALWAYS check the logs folder first to check what went wrong. Check the "Troubleshooting with Logs" section.
|
| 354 |
+
### 1. Shell commands for launching programs
|
| 355 |
+
- Launch flags related
|
| 356 |
+
- Try as hard as possible to minimize launch flags and parameters when launching an app. For example, instead of `python app.py --port 8610`, try to do `python app.py` unless really necessary. The only exception is when the only way to launch the app is to specify the flags.
|
| 357 |
+
- Launch IP related
|
| 358 |
+
- Always try to find a way to launch servers at 127.0.0.1 or localhost, often by specifying launch flags or using environment variables. Some apps launch apps at 0.0.0.0 by default but we do not want this.
|
| 359 |
+
- Launch Port related
|
| 360 |
+
- In case the app itself automatically launches at the next available port by default (for example Gradio does this), do NOT specify port, since it's taken care of by the app itself. Always try to minimize the amount of code.
|
| 361 |
+
- If the install instruction says to launch at a specific port, don't use the hardcoded port they suggest since there's a risk of port conflicts. Instead, use Pinokio's `{{port}}` template expression to automatically get the next available port.
|
| 362 |
+
- For example, if the instruction says `python app.py --port 7860`, don't use that hardcoded port since there might be another app running at that port. Instead, automatically assign the next available port like this: `python app.py --port {{port}}`
|
| 363 |
+
- Note that the `{{port}}` expression always returns the next immediately available port for each step, so if you have multiple steps in a script and use `{{port}}` in multiple steps, the value will be different. So if you want to launch at the next available port and then later reuse that port, you will need to first use `{{port}}` to get the next available port, and save the value in local variable using `local.set`, and then use the `{{local.<variable_name>}}` expression later.
|
| 364 |
+
### 2. shell.run API
|
| 365 |
+
- When writing `shell.run` API requests, always use relative paths (no absolute paths) for the `path` field. For example, if you need to run a command from `app` folder, the `path` attribute should simply be `app`, instead of its full absolute path.
|
| 366 |
+
### 2. Package managers
|
| 367 |
+
- When installing python packages, try best to use `uv` instead of `pip` even if the install instruction says to use pip. Instead of `pip install -r requirements.txt`, you can simply use `uv pip install -r requirements.txt` for example. Even if the project's own README says use pip or poetry, first check if there's a way to use uv instead.
|
| 368 |
+
- When you need to install some global package, try to use `conda` as much as possible. Even on macs, `brew` should be only used if there are no `conda` options.
|
| 369 |
+
### 3. Minimal Always
|
| 370 |
+
- If you are starting with existing script files, before modifying, creating, or removing any script files, first look at `pinokio.js` to understand which script files are actually used in the launcher. The only script files used are the ones mentioned in the `pinokio.js` file. The `pinokio.js` file is the file that constructs the UI dynamically.
|
| 371 |
+
- Do not create a redundant script file that does something that already exists. Instead modify the existing script file for the feature. For example, do not create an `install.json` file for installation if `install.js` already exists. Instead, modify the `install.js` file.
|
| 372 |
+
- Pinokio accepts both JSON and JS script files, so when determining whether a script for a specific purpose already exists, check both JSON and JS files mentioned in the `pinokio.js` file. Do not create script files for rendundant purpose.
|
| 373 |
+
- When building launchers for existing projects cloned from a repository, try to stay away from modifying the project folder (the `C:\pinokio\api\Z-Image-Pinokio.git` folder), even if installations are failing. Instead, try to work around it by creating additional files in the launcher folder, and using those files IN ADDITION to the default project.
|
| 374 |
+
- The only exception when you may need to make changes to the project folder is when the user explicitly wants to modify the existing project. Otherwise if the purpose is to simply write a launcher, the app logic folder should never be touched.
|
| 375 |
+
- When running shell commands, take full advantage of the Pinokio `shell.run` API, which provides features like `env`, `venv`, `input`, `path`, `sudo`, `on`, etc. which can greatly reduce the amount of script code.
|
| 376 |
+
- Python apps: Always use virtual environments via `venv` attribute. This attribute automatically creates a venv or uses if it already exists.
|
| 377 |
+
### 4. Try to support Cross-platform as much as possible
|
| 378 |
+
- Use cross-platform shell commands only.
|
| 379 |
+
- This means, prefer to use commands that work on all platforms instead of the current platform.
|
| 380 |
+
- If there are no cross platform commands, use Pinokio's template expressions to conditionally use commands depending on `platform`, `arch`, etc.
|
| 381 |
+
- Also try to utilize Pinokio Pterm APIs for various cross-platform system features.
|
| 382 |
+
- If it is impossible to implement a cross platform solution (due to the nature of the project itself), set the `platform`, `arch`, and/or `gpu` attributes of the `pinokio.json` file to declare the limitation.
|
| 383 |
+
- Pinokio provides various APIs for cross-platform way of calling commonly used system functions, or lets you selectively run commands depending on `platform`, `arch`, etc.
|
| 384 |
+
### 5. Do not make assumptions about Pinokio API
|
| 385 |
+
- Do NOT make assumptions about which Pinokio APIs exist. Check the documentation.
|
| 386 |
+
- Do NOT make assumptions about the Pinokio API syntax. Follow the documentation.
|
| 387 |
+
### 6. Scripts must be able to replicate install and launch steps 100%
|
| 388 |
+
- The whole point of the scripts is for others to easily download and invoke them via Pinokio interface with one click. Therefore, do not assume the end user's system state, and make everything self-contained.
|
| 389 |
+
- When a 3rd party package needs to be installed, or a 3rd party repository needs to be downloaded, include them in the scripts.
|
| 390 |
+
### 7 Dynamic UI rendering
|
| 391 |
+
- The `pinokio.js` launcher script can change dynamically depending on the current state of the script execution. Which means, depending on what the file returns, it can determine what the sidebar looks like at any given moment of the script cycle.
|
| 392 |
+
- `info.exists(relative_path)`: The `info.exists` can be used to check whether a relative path (relative to the script root path) exists. The `pinokio.js` file can determine which menu items to return based on this value at any given moment.
|
| 393 |
+
- `info.running(relative_path)`: The `info.running` can be used to check whether a script at a relative path is currently running (relative to the script root path) exists. The `pinokio.js` file can determine which menu items to return based on this value at any given moment.
|
| 394 |
+
- `info.local(relative_path)`: The `info.local` can be used to return all the local variables tied to a script that's currently running. The `pinokio.js` file can determine which menu items to return based on this value at any given moment.
|
| 395 |
+
- `default`: set the `default` attribute on any menu item for whichever menu needs to be selected by default at a given step. Some example scenarios:
|
| 396 |
+
- during the install process, the `install.js` menu item needs to be set as the `default`, so it automatically executes the script
|
| 397 |
+
- when launching the `start.js` menu item needs to be set as the `default`, so it automatically executes the script
|
| 398 |
+
- after the app has launched, the `default` needs to be set on the web UI URL, so the user is sent to the actual app automatically.
|
| 399 |
+
- Check the examples in the C:\pinokio\prototype\system\examples folder to see how these are being used.
|
| 400 |
+
### 8. No need for stop scripts
|
| 401 |
+
- `pinokio.js` does NOT need a separate `stop` script. Every script that can be started can also be natively stopped through the Pinokio UI, therefore you do not need a separate stop script for start script
|
| 402 |
+
### 9. Writing launchers for existing projects
|
| 403 |
+
- When writing or modifying pinokio launcher scripts, figure out the install/launch steps by reading the project folder `app`.
|
| 404 |
+
- In most cases, the `README.md` file in the `C:\pinokio\api\Z-Image-Pinokio.git` folder contains the instructions needed to install and run the app, but if not, figure out by scanning the rest of the project files.
|
| 405 |
+
- Install scripts should work for each specific operating system, so ignore Docker related instructions. Instead use install/launch instructions for each platform.
|
| 406 |
+
### 10. Don't use Docker unless really necessary
|
| 407 |
+
- Some projects suggest docker as installation options. But even in these cases, try to find "development" options to launch the app without relying on Docker, as much as possible. We do not need Docker since we can automatically install and launch apps specifically for the user's platform, since we can write scripts that run cross platform.
|
| 408 |
+
### 11. pinokio.json
|
| 409 |
+
- Do not touch the `version` field since the version is the script schema version and the one pre-set in `pinokio.js` must be used.
|
| 410 |
+
- `icon`: It's best if we have a user friendly icon to represent the app, so try to get an image and link it from `pinokio.json`.
|
| 411 |
+
- If the git repository for the `C:\pinokio\api\Z-Image-Pinokio.git` folder points to GitHub (for example https://github.com/<USERNAME>/<REPO_NAME>`, ask the user if they want to download the icon from GitHub, and if approved, get the `avatar_url` by fetching `https://api.github.com/users/<USERNAME>`, and then download the image to the root folder as `icon.png`, and set `icon.png` as the `icon` field of the `pinokio.json`.
|
| 412 |
+
### 12. Gitignore
|
| 413 |
+
- When a launcher involves cloning 3rd party repositories, downloading files dynamically, or some files to be generated, these need to be included in the .gitignore file. This may include things like:
|
| 414 |
+
- Cloning git repositories
|
| 415 |
+
- Downloading files
|
| 416 |
+
- Dynamically creating files during installation or running, such as Sqlite Databases, or environment variables, or anything specific to the user.
|
| 417 |
+
- Make sure these file paths are included in the .gitignore file, and if not, include them in .gitignore.
|
| 418 |
+
|
| 419 |
+
## AI Libraries (Pytorch, Xformers, Triton, Sageattention, etc.)
|
| 420 |
+
If the launcher has a dedicated built-in script named `torch.js`, it can be used as follows:
|
| 421 |
+
|
| 422 |
+
```
|
| 423 |
+
// install.js
|
| 424 |
+
module.exports = {
|
| 425 |
+
run: [
|
| 426 |
+
// Delete this step if your project does not use torch
|
| 427 |
+
{
|
| 428 |
+
method: "script.start",
|
| 429 |
+
params: {
|
| 430 |
+
uri: "torch.js",
|
| 431 |
+
params: {
|
| 432 |
+
path: "app",
|
| 433 |
+
venv: "venv", // Edit this to customize the venv folder path
|
| 434 |
+
// xformers: true // uncomment this line if your project requires xformers
|
| 435 |
+
// triton: true // uncomment this line if your project requires triton
|
| 436 |
+
// sageattention: true // uncomment this line if your project requires sageattention
|
| 437 |
+
}
|
| 438 |
+
}
|
| 439 |
+
},
|
| 440 |
+
// Edit this step with your custom install commands
|
| 441 |
+
{
|
| 442 |
+
method: "shell.run",
|
| 443 |
+
params: {
|
| 444 |
+
venv: "venv", // Edit this to customize the venv folder path
|
| 445 |
+
path: "app",
|
| 446 |
+
message: [
|
| 447 |
+
"uv pip install -r requirements.txt"
|
| 448 |
+
],
|
| 449 |
+
}
|
| 450 |
+
},
|
| 451 |
+
]
|
| 452 |
+
}
|
| 453 |
+
```
|
| 454 |
+
|
| 455 |
+
The `torch.js` script also includes ways to install pytorch dependent libraries such as xformers, triton, sagetattention. If any of these libraries need to be installed, use the torch.js to install in order to install them cross platform.
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
## Quick Reference
|
| 459 |
+
### Essential Documentation
|
| 460 |
+
- **Pinokio Programming:** See `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md β "Programming Pinokio" section
|
| 461 |
+
- **Dynamic Menus:** See `PINOKIO.md` at C:\pinokio\prototype\PINOKIO.md β "Dynamic menu rendering" section
|
| 462 |
+
- **CLI Commands:** See `PTERM.md` at C:\pinokio\prototype\PTERM.md
|
| 463 |
+
### Common Patterns
|
| 464 |
+
- **Python Virtual Env:** `shell.run` with `venv` attribute
|
| 465 |
+
- **Cross-platform Commands:** Always test on multiple platforms
|
| 466 |
+
- **Error Handling:** Check logs/api for launcher issues
|
| 467 |
+
- **GitHub Operations:** Use `gh` CLI for advanced GitHub features
|
| 468 |
+
## Development Principles
|
| 469 |
+
1. **Minimize Shell Usage:** Leverage API parameters instead of raw commands
|
| 470 |
+
2. **Maintain Separation:** Keep app logic and launchers separate
|
| 471 |
+
3. **Follow Conventions:** Match existing project patterns
|
| 472 |
+
4. **Test Thoroughly:** Use CLI to verify launcher functionality
|
| 473 |
+
5. **Document Changes:** Update relevant metadata and documentation
|