Try Linux on Android - Termux XFCE Installation (for beginners)
Requirements
| Resource | Amount |
|----------------|--------|
| RAM | 4GB |
| Storage | 3GB |
| Internet Data | 450MB |
APK
- Termux: termux/termux-app
- Termux X11: termux/termux-x11
Permissions
- Notification: important to edit preferences and to stop the app
- Storage: necessary to read-write files
Installation
1. Open Termux, then allow storage access:
termux-setup-storage
2. Change repository:
termux-change-repo
3. Update & upgrade:
pkg update && pkg upgrade -y
4. Hide welcome message:
touch ~/.hushlogin
5. Add repositories:
pkg in tur-repo x11-repo termux-x11-nightly
6. Install the essentials:
pkg in xfce4 ffmpeg ffmpegthumbnailer mousepad ristretto neofetch firefox vlc-qt xfce4-whiskermenu-plugin
7. Start the desktop:
termux-x11 :0 -xstartup "dbus-launch --exit-with-session xfce4-session"
8. Open Termux X11
Enjoy Linux!
35 points · 4 comments
How to Build Your Own Smart AI Assistant Using Only Your Android Phone (Termux + Python)
How to Build Your Own Smart AI Assistant Using Only Your Android Phone (Termux + Python)
Have you ever wanted to build your own AI assistant but assumed you needed an expensive computer, powerful graphics card or years of programming experience?
What if I told you that you could build a working AI assistant using nothing more than your Android phone?
You don't need a laptop.
You don't need an expensive development environment.
You don't even need to be an experienced programmer.
With Termux, Python and an AI API, you can create a personal AI assistant directly from your Android device.
In this tutorial, we're going to build one step by step.
But we're not going to stop at creating a basic chatbot that simply accepts a question and returns an answer.
We'll build an assistant that has:
- Its own personality and instructions.
- The ability to hold conversations.
- Short-term conversational memory.
- A customizable name.
- The ability to remember previous messages during a session.
- Commands to reset conversations and exit.
- Basic error handling.
- A simple terminal interface.
By the end, you'll understand how the different parts work and how to extend the project into something more advanced.
You can follow this tutorial even if you've never built an AI application before.
Let's get started.
1. First, Understand What We're Building
Before installing anything, let's understand how our assistant will work.
An AI assistant generally has several components.
1. The interface
This is where you communicate with your assistant.
In our project, the interface will be the Termux terminal.
2. The programming language
We'll use Python to handle the application's logic.
Python will receive your messages, organize conversation history and communicate with the AI service.
3. The AI model
This is the component responsible for understanding questions and generating intelligent responses.
Instead of training a massive AI model ourselves, we'll connect our application to an existing model through an API.
4. Memory
We'll create a system that keeps previous messages during the conversation.
This allows the assistant to understand follow-up questions.
For example:
You: My name is Daniel.
Assistant: Nice to meet you, Daniel!
You: What is my name?
Assistant: Your name is Daniel.
Without conversation history, the assistant might not understand the second question.
5. Personality and instructions
We'll give our assistant specific instructions about how it should communicate, explain things and respond to users.
This is what makes it behave more like a personal assistant rather than a generic chatbot.
How everything connects
Our application will follow this process:
1. You enter a message.
2. Python receives the message.
3. Python adds it to the conversation history.
4. The application sends the conversation to the AI model.
5. The AI generates a response.
6. Python displays the response.
7. The conversation history is updated.
That's the basic architecture.
An important distinction: Termux and Python will run on your phone, but the AI model will run on a remote server. Therefore, this first version requires an internet connection.
Your phone is building and controlling the assistant, not performing the expensive AI inference itself.
2. What You Need Before Starting
You only need three main things.
A. An Android phone
Any reasonably modern Android device supported by the current Termux release should be suitable for this lightweight project.
You don't need a flagship phone.
Our application will not be running a massive language model locally.
B. Termux
Termux is an Android terminal emulator and Linux environment.
It allows you to run programming languages, install development packages and execute commands directly from your phone.
Download it from an official distribution linked by the Termux project.
- Termux website: termux.dev
- Official GitHub repository: termux/termux-app
Avoid mixing Termux installations from different distribution sources. Its companion applications and plugins should come from the same source.
C. An AI API key
We'll use an AI API to connect our Python application to an existing language model.
An API allows one application to communicate with another application or service.
For example, instead of building a language model capable of understanding thousands of different questions, we send the question to an existing AI model and receive its response.
You can explore available models and API access through:
platform.openai.com
You may need to create an account and configure API billing.
Important: API usage may cost money. Check the current pricing and your account's available access before making requests.
Also, an API key is a private credential. Never publish it in your code, GitHub repository or screenshots.
3. Prepare Termux for Development
Open Termux.
You should see a terminal where you can enter commands.
Don't worry if this looks unfamiliar. We'll explain what each command does.
First, update the installed package information.
Enter:
pkg update && pkg upgrade -y
This checks for available package updates and installs them.
Next, install Python:
pkg install python -y
Python is the programming language we'll use to build the assistant.
Check whether the installation was successful:
python --version
You should see a Python version displayed.
Now install Git:
pkg install git -y
Git is a version-control tool that helps developers manage changes to their projects.
We won't need Git for the basic assistant, but it's useful to have when developing larger applications.
Next, upgrade pip:
python -m pip install --upgrade pip
Pip is Python's package installer. It allows us to install additional libraries.
Our development environment is now ready.
4. Create Your AI Assistant Project
Let's create a dedicated folder for the project.
Enter:
mkdir smart-ai
This creates a directory called "smart-ai".
Move into it:
cd smart-ai
Your terminal is now working inside the project directory.
Let's create a Python virtual environment.
python -m venv venv
A virtual environment gives your project its own Python package installation space.
Activate it:
source venv/bin/activate
If activation succeeds, you should see something similar to "(venv)" at the beginning of your terminal prompt.
This helps keep project dependencies separate from other Python projects.
Now install the official OpenAI Python library:
python -m pip install openai
Wait for the installation to finish.
The library allows our Python application to communicate with the OpenAI API without manually constructing every HTTP request.
We are now ready to write the actual assistant.
5. Create Your AI API Key
Before writing the code, we need to configure access to the AI model.
Visit:
platform.openai.com
Sign in and navigate to the API key section.
Create a new secret API key.
Copy it somewhere temporarily safe.
Do not share it with anyone.
Return to Termux.
Enter:
export OPENAI_API_KEY="YOUR_API_KEY_HERE"
Replace "YOUR_API_KEY_HERE" with your actual API key.
For example, the command should follow this structure:
export OPENAI_API_KEY="sk-your-private-key"
The example above is illustrative, not a working key.
This command creates an environment variable that Python can access.
Why not simply put the API key inside the Python script?
Because separating credentials from application code reduces the chance of accidentally exposing them when sharing your project.
Remember that environment variables set this way generally apply to the current shell session. You'll need to configure the key again when starting a new session unless you set up a secure alternative.
Never upload your real key to GitHub.
6. Create the Main AI Assistant
Now comes the exciting part.
We're going to create the actual application.
Create a Python file:
nano assistant.py
Nano is a terminal text editor.
Paste the following complete code into the editor.
import os
from openai import OpenAI
Check API credentials
API_KEY = os.getenv("OPENAI_API_KEY")
if not API_KEY:
print("Error: OPENAI_API_KEY is not configured.")
raise SystemExit(1)
Initialize AI client
client = OpenAI(api_key=API_KEY)
Choose a model available to your account
MODEL = os.getenv("OPENAI_MODEL", "gpt-6-luna")
Assistant personality
SYSTEM_PROMPT = """
You are Nova, a smart and helpful personal AI assistant.
Your responsibilities:
1. Give accurate and useful answers.
2. Explain complicated topics in simple language.
3. Be friendly, respectful and conversational.
4. Ask for clarification when a question is unclear.
5. Avoid inventing information.
6. Admit when you do not know something.
7. Help users solve problems step by step.
8. Keep simple questions concise.
9. Provide detailed explanations when necessary.
You should behave like a thoughtful personal assistant,
not a machine that simply generates random text.
"""
Conversation history
conversation = [
{
"role": "system",
"content": SYSTEM_PROMPT
}
]
Display welcome screen
def welcome():
print("\n" + "=" * 45)
print(" NOVA AI ASSISTANT")
print("=" * 45)
print("Your personal AI assistant")
print("Powered by Python and an AI model")
print("\nCommands:")
print("/reset - Start a new conversation")
print("/exit - Close the assistant")
print("=" * 45)
Generate AI response
def generate_response(user_message):
conversation.append({
"role": "user",
"content": user_message
})
try:
response = client.responses.create(
model=MODEL,
input=conversation
)
answer = response.output_text
conversation.append({
"role": "assistant",
"content": answer
})
return answer
except Exception as error:
conversation.pop()
print("\nSomething went wrong:")
print(error)
return None
Main application
def main():
welcome()
while True:
try:
user_message = input("\nYou: ").strip()
if not user_message:
continue
# Exit command
if user_message.lower() == "/exit":
print("\nNova: Goodbye! See you again.")
break
# Reset conversation
if user_message.lower() == "/reset":
conversation.clear()
conversation.append({
"role": "system",
"content": SYSTEM_PROMPT
})
print("\nNova: Conversation reset!")
continue
# Generate answer
print("\nNova is thinking...")
answer = generate_response(user_message)
if answer:
print("\nNova:", answer)
except KeyboardInterrupt:
print("\n\nNova: Assistant stopped.")
break
if name == "main":
main()
Save your file
If you're using Nano:
1. Press CTRL + O.
2. Press Enter to confirm the filename.
3. Press CTRL + X to exit.
Your Python application is now saved.
What did we just create?
Let's understand the important sections.
The API connection
client = OpenAI(api_key=API_KEY)
This initializes the API client.
It allows our application to communicate with the AI service.
The assistant's personality
SYSTEM_PROMPT = """
You are Nova, a smart and helpful personal AI assistant.
"""
This defines the assistant's behaviour.
You can change the instructions to create a different personality.
For example, you could build:
- A programming tutor.
- A personal study assistant.
- A business assistant.
- A writing assistant.
- A research assistant.
The underlying AI model remains the same, but the instructions influence how it responds.
The conversation memory
conversation = [
{
"role": "system",
"content": SYSTEM_PROMPT
}
]
This creates the initial conversation history.
Every user message and assistant response is added to this list.
When we send the conversation to the model, it receives the available context.
This is how our assistant can understand follow-up questions.
However, this is short-term conversational memory, not permanent personal memory.
The conversation currently exists in the running Python process. Closing the application clears it.
The AI response
response = client.responses.create(
model=MODEL,
input=conversation
)
This is where the actual AI interaction happens.
We send the conversation to the Responses API.
The model processes the information and generates a response.
We then retrieve the generated text:
answer = response.output_text
Finally, the application displays it in Termux.
7. Run Your AI Assistant for the First Time
Now let's test everything.
Make sure you're still inside the "smart-ai" directory and your virtual environment is activated.
Run:
python assistant.py
If everything is configured correctly, you should see:
=============================================
NOVA AI ASSISTANT
=============================================
Your personal AI assistant
Powered by Python and an AI model
Commands:
/reset - Start a new conversation
/exit - Close the assistant
=============================================
You:
Congratulations!
You have created your first AI-powered assistant using only your Android phone.
Try asking:
Hello, who are you?
Then:
Explain artificial intelligence to me.
Now test its conversational memory:
My name is Daniel.
Follow that with:
What is my name?
The assistant should use the previous message to answer.
You can also test:
/reset
This clears the current conversation.
And:
/exit
This closes the application.
If the model identifier in the example is not available to your API account, check the provider's current model catalogue and set another supported model:
export OPENAI_MODEL="YOUR_AVAILABLE_MODEL"
Then run the application again.
8. How to Make Your Assistant Smarter
At this stage, you have a functioning AI assistant.
But what makes it smart?
The language model provides the intelligence. Our Python application controls how that intelligence is accessed and presented.
There are several ways to improve the assistant.
A. Give It a Better Personality
You can change the system instructions.
For example, replace the original personality with:
SYSTEM_PROMPT = """
You are Atlas, an intelligent learning assistant.
Your mission is to help people understand
technology, science, programming and everyday problems.
Always explain difficult concepts using simple examples.
When teaching programming:
1. Explain the concept.
2. Show a practical example.
3. Explain the code.
4. Identify common mistakes.
5. Give the learner a small exercise.
Never pretend to know something you do not know.
Prioritize understanding over simply giving answers.
"""
Now you have a learning-focused assistant.
B. Give It a Different Name
Find:
print("NOVA AI ASSISTANT")
Replace it with:
print("ATLAS AI ASSISTANT")
You can also change the name inside the system instructions.
C. Limit Conversation History
Our current application sends the entire conversation history with every request.
This is useful for understanding previous messages, but long conversations can become expensive and eventually exceed the model's context limit.
A simple improvement is to retain only the most recent messages.
For example, after adding an assistant response, you could use:
conversation[:] = [
conversation[0]
] + conversation[-20:]
This retains the system instructions and the latest 20 conversation messages.
For a production application, history management should be more careful so that user and assistant messages remain properly paired.
D. Make It Remember Conversations Between Sessions
Currently, closing Termux clears the conversation.
You can extend the project by saving conversation history to a local JSON file.
Python includes a built-in library for this:
import json
You could save the conversation using:
with open("memory.json", "w") as file:
json.dump(conversation, file, indent=4)
And load it when the application starts:
with open("memory.json", "r") as file:
conversation = json.load(file)
These are basic examples. A complete implementation should handle missing files, invalid JSON, reset behaviour and private data.
Also, understand the distinction between conversation history and long-term memory.
Conversation history stores what was said.
A more advanced memory system identifies useful information, stores it separately and retrieves relevant details when needed.
You could eventually give your assistant the ability to remember a user's preferred programming language, ongoing projects or learning goals.
However, users should have control over what is stored and the ability to delete it.
9. Troubleshooting Common Problems
If something doesn't work, don't immediately assume your phone is incompatible.
Here are some common problems.
Problem 1: Python command not found
You probably haven't installed Python correctly.
Run:
pkg install python
Then check:
python --version
Problem 2: No module named openai
The Python library may not have been installed in your active environment.
Activate your virtual environment:
source venv/bin/activate
Install the library:
python -m pip install openai
Problem 3: API key not found
Check whether your environment variable exists:
echo $OPENAI_API_KEY
If it is empty, configure your API key again:
export OPENAI_API_KEY="YOUR_API_KEY"
Problem 4: Authentication error
Check that:
- Your API key is correct.
- Your key has not been revoked.
- Your API account has access.
- Your account has the necessary billing configuration.
Never share your API key when requesting technical assistance.
Problem 5: Model not found
The model name might not be available to your account.
Check the provider's current model documentation and select an accessible model.
Problem 6: Connection errors
The application needs internet access.
Check your connection and try again.
Remember that Termux runs on Android, so Android may also restrict background processes or terminate long-running sessions.
For this beginner project, keep Termux open while using the assistant.
10. What Can You Build Next?
You now have a basic AI assistant.
But this is only the beginning.
The interesting part of software development is taking a working foundation and gradually introducing more useful features.
Here are some ideas.
1. Voice assistant
Add speech recognition so that users can speak instead of typing.
You could also add text-to-speech so the assistant can read responses aloud.
2. Web interface
Instead of communicating through the terminal, create a browser-based interface using Python and a lightweight web framework.
You could build a proper chat interface with message bubbles, a conversation sidebar and a responsive design.
3. Document assistant
Allow users to provide documents and ask questions about their contents.
For example, a student could provide study notes and ask the assistant to explain particular sections.
4. Programming assistant
Create a specialized assistant that explains programming errors, reviews code and helps beginners understand unfamiliar concepts.
5. Long-term memory
Develop a system that stores useful information between conversations.
You could use SQLite or another database to organize saved information.
6. Tool integration
Eventually, your assistant could perform useful actions rather than simply answering questions.
For example, it could calculate values, organize information or interact with approved external services.
This is an important step towards building an AI agent.
An AI chatbot responds to messages.
An AI agent can also use tools to complete tasks, subject to the permissions and rules you give it.
11. Can You Build an AI That Works Completely Offline?
Yes, but it is a different project.
The assistant we created uses a remotely hosted model.
If your internet connection disappears, it cannot generate new AI responses.
A completely offline assistant requires a language model that can run locally on your Android device.
Projects such as llama.cpp explore running language models on different hardware platforms.
However, local AI has additional requirements.
Your device needs sufficient:
- Available storage.
- RAM.
- Processing power.
- Compatible software.
- Battery capacity.
Larger models generally require more resources.
A small quantized model may be practical on some devices, while a larger model might be extremely slow or fail to run because of memory limitations.
Termux also has Android-specific compatibility considerations.
Don't assume that every Linux AI installation tutorial will work on Android without modification.
For a beginner, starting with an API-powered assistant is usually easier.
Once you understand how the application works, you can experiment with local inference.
12. Final Thoughts: You Don't Need an Expensive Computer to Start Building AI
One of the biggest barriers to learning software development is the belief that you need expensive equipment before you can begin.
That's not always true.
An Android phone can provide a surprisingly useful development environment.
With Termux and Python, you can experiment with programming, create small applications and communicate with powerful AI models.
Of course, a phone has limitations. A larger screen and more powerful hardware make complex development easier.
But the most important thing is getting started.
You now understand how to:
- Prepare a Python development environment.
- Install programming libraries.
- Connect an application to an AI API.
- Create an assistant personality.
- Manage conversational context.
- Handle basic errors.
- Extend an AI application with additional features.
Don't just copy the code and stop there.
Change the assistant's name. Experiment with its personality. Add new commands. Try saving conversations. Break something, investigate it and fix it.
The best way to become a developer is not simply to follow tutorials.
It is to understand what you're building and gradually become confident enough to create your own solutions.
If you managed to build Nova, you've already taken your first practical step.
Your phone is not just a device for consuming technology. It can also be a tool for creating it.
---
A little more inspiration
I believe technology becomes most valuable when it helps people solve real problems.
That is also an idea behind AfriWidget, a project focused on building practical digital tools for education, productivity and everyday needs.
If you're interested in seeing how relatively simple web technologies can become useful products, take a look at "AfriWidget" (afriwidget.com).
You don't always need to build the biggest technology to make a meaningful difference. Sometimes, solving one problem properly is a great place to start.
---
Further Reading
- "Termux official documentation" (termux.dev)
- "Termux GitHub repository" (termux/termux-app)
- "Python documentation" (docs.python.org)
- "OpenAI API documentation" (platform.openai.com)
- "OpenAI API pricing" (platform.openai.com)
- "llama.cpp GitHub repository" (ggml-org/llama.cpp)
Disclaimer: This tutorial demonstrates an API-powered AI assistant for educational purposes. API availability, model identifiers, account requirements and pricing can change. Keep your API credentials private and review your provider's current terms before using the application.
こっちは未マージ
termux-app#5238
34 views
🚀 TERMUX — TURN YOUR ANDROID PHONE INTO A POWERFUL TERMINAL!💻📱
📥 DOWNLOAD TERMUX FROM THESE SOURCES
GitHub Releases:
github.com/termux/termux-app/releases
F-Droid :
f-droid.org
#Termux #Android #Linux #Programming #Python #OpenSource #CyberSecurity
@Noisbethever t.co
11 views
Need a terminal on your Android phone? 📱
Termux gives you a Linux-like environment for Git, SSH and Python. Handy for quick tasks away from your laptop. ⌨️
termux/termux-app
#Android #浇朋友 #蓝朋友 #互关 #fo
1 like · 92 views
手机上也想用 Git、SSH 和 Python?📱
Termux 给 Android 带来终端与 Linux 环境。出门也能跑命令、连服务器。⌨️
termux/termux-app
#Android #浇朋友 #蓝朋友 #互关 #fo
53 views
Cara Install Termux + X11 di Android via Github (2026)
Cara install dan setup awal Termux beserta Termux:X11 di Android dari nol.
Di video ini gw bahas versi Termux dan Termux:X11 yang paling stabil (bukan versi Play Store).
🔗 Join Telegram Group:
t.me
🔗 Link Download:
- Termux (GitHub): termux/termux-app
- Termux:X11 (GitHub): termux/termux-x11
💻 Command yang dipakai di video:
pkg update && pkg upgrade
⏱️ Timestamps:
00:00 Intro
00:08 Kenapa jangan versi Play Store?
00:15 Download Termux
01:20 Download Termux:X11
01:37 Install Termux + Termux:X11
02:12 Update & Upgrade Package
Di video selanjutnya, kita bakal langsung install Linux Desktop Environment di atas setup Termux:X11 ini.
💻 Device
Lenovo Legion Tab (8.8″ Gen 2)
s.shopee.co.id
#termux #termuxx11 #linuxandroid #android #tutorialtermux
1 like · 1 comment · 220 views
Sentinel-IR 0.1.2:在 Android Termux 上安装、分析 JavaScript 并验证 AST 检测结果
!Image description
无需电脑、无需 Root、无需 API Key:直接用 Android 手机运行 JavaScript 结构分析与回归测试。
Sentinel-IR 是一个用于 JavaScript 代码结构分析的开源工具。它可以从源代码中提取路由、模块导入、环境变量、文件系统操作、网络相关操作以及潜在风险信号,并将这些信息整理成紧凑的结构化报告。
对于 AI Agent 来说,这意味着不必在每一次分析中都直接传入整个源文件。系统可以先获得一份结构化的事实摘要,再根据任务决定是否需要查看原始代码。
本文将两个实践指南合并为一套完整流程:
- 从零开始在 Android Termux 中安装 Sentinel-IR。
- 初始化随 npm 包提供的 WebAssembly 解析器。
- 分析一个可复现的 JavaScript 示例。
- 检查 JSON 报告中的结构化事实。
- 使用 Sentinel-IR 0.1.2 验证动态代码执行、变量作用域和 "child_process" 检测。
- 运行针对特定回归场景的测试。
- 检查发布包,并在需要时运行完整开发测试套件。
- 了解分析器的限制,以及如何安全地分享测试结果。
项目链接
- npm 包:npmjs.com
- Sentinel-IR 0.1.2:npmjs.com
- GitLab 源代码:gitlab.com
- 0.1.1 到 0.1.2 的代码变更:gitlab.com
---
一、开始之前:需要准备什么?
你需要:
- 一部能够运行 Termux 的 Android 手机。
- 可以访问软件仓库和 npm registry 的网络连接。
- 一些可用存储空间。
- 大约 20 至 30 分钟,具体时间取决于下载速度和设备环境。
不需要 Root 权限、桌面电脑、OpenAI 账户或 AI API Key。
安装 Termux
建议从官方渠道获取 Termux:
- F-Droid:f-droid.org
- 官方 GitHub:termux/termux-app
不要随意安装聊天群或不明下载网站提供的 APK。
如果手机上已经安装了 Termux,不要为了本教程直接卸载。来自不同发行渠道的版本可能使用不同的签名密钥。
本文的验证原则
本文区分三种不同的检查:
1. 安装检查:确认安装的是指定版本的 npm 包。
2. 功能检查:确认解析器能处理给定的 JavaScript 示例,并输出预期事实。
3. 回归测试:确认特定语法和作用域场景得到预期分类。
通过其中一种检查,不等于证明整个程序安全,也不等于证明分析器覆盖了所有 JavaScript 语法。
二、打开 Termux 并更新软件包
打开 Termux,等待终端提示符出现。
一次复制一个命令块,执行后等待命令结束,再继续下一步。
不要复制文档中的提示符 "$",只复制代码块里的命令。
第 1 步:更新 Termux
运行:
pkg update && pkg upgrade -y
这会更新软件包列表并升级已安装的软件包。
如果遇到仓库或镜像错误,先解决软件源问题,不要直接跳过。
第 2 步:安装 Node.js 和 npm
Sentinel-IR 要求 Node.js 20 或更新版本。
pkg install nodejs -y
检查版本:
node --version
npm --version
进一步检查 Node.js 主版本:
node -e "const major = Number(process.versions.node.split('.')[0]); console.log('Node.js:', process.version); if (major < 20) { console.error('Sentinel-IR requires Node.js 20 or newer'); process.exit(1); } console.log('PASS: Node.js version is supported');"
预期结果:
PASS: Node.js version is supported
如果 Node.js 版本低于 20,请先更新 Termux 软件包并检查可用版本。
三、创建独立测试目录
为了避免修改其他项目,我们先创建一个专门的测试目录。
mkdir -p "$HOME/sentinel-ir-termux-test"
cd "$HOME/sentinel-ir-termux-test"
pwd
输出路径通常以以下内容开头:
/data/data/com.termux/files/home/
后续测试文件都放在这个目录中。
以后可以使用以下命令返回:
cd "$HOME/sentinel-ir-termux-test"
四、安装指定版本 Sentinel-IR 0.1.2
本教程以 0.1.2 为主要验证版本。
首先创建一个最小 npm 项目:
npm init -y
安装指定版本:
npm install --save-exact sentinel-ir@0.1.2
检查实际安装的版本:
npm ls sentinel-ir
预期依赖树中包含:
sentinel-ir@0.1.2
然后检查公共 npm registry:
npm view sentinel-ir@0.1.2 version
npm view sentinel-ir dist-tags --json
版本查询应返回:
0.1.2
发行标签中应包含:
{
"latest": "0.1.2"
}
这里有一个重要区别:本地 "package.json" 中写着某个版本,并不能证明该版本已经在公共 npm registry 中发布。registry 查询可以独立验证这一点。
如果 npm 无法访问 registry,请先检查网络连接:
npm ping
不要把网络超时直接当作分析器故障。
五、检查公开 API
运行以下命令,确认需要的函数已经导出:
node - <<'NODE'
const sentinel = require('sentinel-ir');
for (const name of ['analyzeAsync', 'compress', 'initializeWasm']) {
console.log(${name}: ${typeof sentinel[name]});
if (typeof sentinel[name] !== 'function') {
console.error(FAIL: missing function ${name});
process.exitCode = 1;
}
}
if (!process.exitCode) {
console.log('PASS: expected Sentinel-IR functions are exported');
}
NODE
预期结果应包含:
analyzeAsync: function
compress: function
initializeWasm: function
PASS: expected Sentinel-IR functions are exported
如果出现 "Cannot find module",请检查当前目录和安装状态:
cd "$HOME/sentinel-ir-termux-test"
npm ls sentinel-ir
如果安装的不是 0.1.2,请返回安装步骤。
六、初始化 WebAssembly 解析器
Sentinel-IR 包含 WebAssembly 解析路径。在 Android 等环境中,如果可选的原生 Tree-sitter 依赖无法正常构建,可以尝试使用该路径。
运行:
node - <<'NODE'
const { initializeWasm } = require('sentinel-ir');
initializeWasm()
.then(() => {
console.log('PASS: Sentinel-IR WebAssembly parser initialized');
})
.catch((error) => {
console.error('FAIL: WebAssembly initialization failed');
console.error(error);
process.exitCode = 1;
});
NODE
预期结果:
PASS: Sentinel-IR WebAssembly parser initialized
如果初始化失败,先不要继续假设解析器已经可以工作。
检查安装版本及相关依赖:
npm ls sentinel-ir web-tree-sitter
ls -lh node_modules/sentinel-ir/wasm/
检查包中是否包含 JavaScript 对应的 WebAssembly 语法文件:
tree-sitter-javascript.wasm
文件缺失、安装不完整或依赖初始化失败,都需要单独调查。
七、创建一个可复现的 JavaScript 示例
接下来创建一个简单的 Express 风格服务器代码。
注意:这里仅分析源代码,不会运行服务器,也不需要安装 Express。
创建文件:
cat > sample.js <<'JS'
const express = require("express");
const fs = require("fs");
const app = express();
app.post("/upload", (req, res) => {
fs.writeFileSync("/tmp/upload", req.body);
res.end();
});
app.listen(process.env.PORT);
JS
检查文件内容:
cat sample.js
检查语法:
node --check sample.js
如果语法正确,Node.js 通常不会输出任何内容,并会返回终端提示符。
这个示例刻意包含几个容易识别的结构:
- "POST /upload" 路由。
- "express" 和 "fs" 模块导入。
- "process.env.PORT" 环境变量。
- 文件系统写入操作。
这些结构可以用来检查分析器是否提取了预期事实。
八、创建分析脚本
下面的脚本读取指定 JavaScript 文件,将源代码传给 "analyzeAsync()",再通过 "compress()" 生成紧凑报告。
它不会执行输入文件,也不会调用 LLM 或上传源代码。
创建脚本:
cat > analyze.js <<'JS'
const fs = require('node:fs/promises');
const path = require('node:path');
const { analyzeAsync, compress } = require('sentinel-ir');
async function main() {
const inputPath = process.argv[2];
if (!inputPath) {
console.error('Usage: node analyze.js <file.js>');
process.exitCode = 1;
return;
}
const source = await fs.readFile(inputPath, 'utf8');
const ir = await analyzeAsync(source, {
target: path.basename(inputPath),
});
const report = compress(ir);
console.log(JSON.stringify(report, null, 2));
if (report.analysisStatus !== 'complete') {
console.error(
'WARNING: analysisStatus is not complete. Do not treat this result as a complete structural analysis.'
);
process.exitCode = 2;
}
}
main().catch((error) => {
console.error('ERROR: analysis could not finish.');
console.error(error && error.stack ? error.stack : error);
process.exitCode = 1;
});
JS
检查脚本自身的语法:
node --check analyze.js
这一步只验证包装脚本的语法,不验证 Sentinel-IR 的检测准确性。
九、运行分析并保存 JSON 报告
执行:
node analyze.js sample.js > report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
查看报告:
cat report.json
退出码含义:
- "0":脚本生成了 "analysisStatus" 为 "complete" 的报告。
- "2":生成了报告,但分析状态不完整。
- "1":脚本无法完成分析,例如无法读取文件或初始化解析器失败。
对于本文提供的有效 JavaScript 示例,预期可以检查以下内容:
- "analysisStatus" 为 "complete"。
- "facts.ast" 为 "true"。
- "facts.routes" 包含 "POST /upload"。
- "facts.imports" 包含 "express" 和 "fs"。
- "facts.env" 包含 "PORT"。
- 报告中包含与路由和文件写入相关的操作或风险信号。
实际报告中的其他字段及其格式可能随输入和实现而变化。
还可以单独查看主要字段:
node - <<'NODE'
const r = require('./report.json');
console.log('analysisStatus:', r.analysisStatus);
console.log('routes:', r.facts.routes);
console.log('imports:', r.facts.imports);
console.log('environment variables:', r.facts.env);
console.log('operations:', r.facts.operations);
console.log('risk signals:', r.facts.riskSignals);
NODE
十、自动验证预期结果
仅仅看到一份 JSON 并不意味着分析正确。
我们可以编写一个小检查程序,对示例中的已知结构进行断言。
node - <<'NODE'
const report = require('./report.json');
const failures = [];
if (report.analysisStatus !== 'complete') {
failures.push(analysisStatus expected complete, got ${report.analysisStatus});
}
if (report.facts?.ast !== true) {
failures.push('facts.ast expected true');
}
if (!Array.isArray(report.facts?.routes) ||
!report.facts.routes.includes('POST /upload')) {
failures.push('expected route POST /upload was not found');
}
if (!Array.isArray(report.facts?.imports) ||
!report.facts.imports.includes('express')) {
failures.push('expected import express was not found');
}
if (!Array.isArray(report.facts?.imports) ||
!report.facts.imports.includes('fs')) {
failures.push('expected import fs was not found');
}
if (!Array.isArray(report.facts?.env) ||
!report.facts.env.includes('PORT')) {
failures.push('expected environment variable PORT was not found');
}
if (failures.length) {
console.error('FAIL: sample analysis did not match expectations');
for (const failure of failures) {
console.error(- ${failure});
}
process.exitCode = 1;
} else {
console.log('PASS: the sample produced the expected structural facts');
}
NODE
预期结果:
PASS: the sample produced the expected structural facts
这是一个可复现的 smoke test。它证明的是:在当前安装环境中,给定示例产生了检查程序所要求的结构化事实。
它不是完整的安全审计,不是全面的准确率基准测试,也不证明所有 JavaScript 模式都能被正确识别。
十一、尝试分析自己的 JavaScript 文件
完成已知示例的测试后,可以尝试分析自己拥有或有权检查的 JavaScript 文件。
选项 A:文件已经位于 Termux 中
将文件复制到测试目录,或者直接使用其路径。
node analyze.js ./your-file.js > your-file-report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
将 "your-file.js" 替换成实际文件名。
请为报告使用不同的文件名,避免覆盖之前的 "report.json"。
选项 B:文件位于 Android Downloads
如果需要访问 Android 的共享存储,可以执行:
termux-setup-storage
按照 Android 显示的权限提示进行授权。
列出下载目录:
ls "$HOME/storage/downloads"
复制一个 JavaScript 文件:
cp "$HOME/storage/downloads/example.js" "$HOME/sentinel-ir-termux-test/your-file.js"
cd "$HOME/sentinel-ir-termux-test"
node analyze.js your-file.js > your-file-report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
将 "example.js" 替换成实际文件名。
如果文件名包含空格,请保留命令中的引号。
重要限制
Sentinel-IR 当前面向 JavaScript,包括 CommonJS 和 ESM。
它不声称能够可靠地分析所有 TypeScript、复杂 JSX 或其他编程语言。
此外,分析器一次处理一个 JavaScript 文件,不会自动完成跨文件调用图或数据流分析。
十二、理解 analysisStatus
"analysisStatus" 是理解报告时最重要的字段之一。
complete
表示 AST 提取成功,源代码解析没有出现导致分析不完整的语法错误。
但这不代表已经发现所有安全问题,也不代表程序一定安全。
incomplete
表示 AST 提取不可用,或者源代码未能被完整解析。
此时输出可能依赖基于文本的回退启发式规则,结果可能出现误报或漏报。
如果报告不完整,不要声称 Sentinel-IR 已经确认该文件安全。
建议检查:
node --check sample.js
确认输入是受支持的 JavaScript,并尝试缩小问题示例。
即使状态为 "complete",仍然存在明确的分析边界:
- 这是基于语法结构的分析,不是完整语义分析。
- 一次只分析一个文件。
- 不一定能解析别名、动态计算的属性名或跨模块传递的行为。
- 不证明应用程序安全。
- 不能消除 Prompt Injection。
- 不会运行应用程序,也不会替 AI Agent 决定应该采取什么行动。
像 "world.confidence" 这样的字段,也不应被误解为经过统计校准的正确率概率。
---
第二部分:Sentinel-IR 0.1.2 的 AST 检测改进
十三、为什么 0.1.2 值得单独测试?
0.1.2 的重点不是重新设计整个 API,而是改善若干具体 JavaScript 语法场景中的结构化事实提取。
本次发布重点包括:
1. 识别更多动态代码执行形式。
2. 更好地区分全局 "eval"、"Function" 与同名局部变量。
3. 识别部分使用字符串字面量的计算属性方法调用。
4. 将静态 "child_process" 导入记录为一种潜在能力。
5. 通过回归测试检查正确识别和正确不识别的情况。
在发布验证记录中,开发测试套件通过了 69 项测试,GitLab CI 的三个任务全部成功,独立消费者环境中的定向测试通过了 8 项。
这些结果支持特定实现和测试场景,不代表完整的 JavaScript 安全覆盖。
十四、变量名称相同,不代表行为相同
考虑以下代码:
eval(userInput);
以及:
parser.eval(userInput);
两者都包含 "eval",但不一定执行相同的操作。
第一种形式通常调用全局 "eval",除非该名称被局部绑定遮蔽。
第二种形式调用 "parser" 对象的方法。它可能只是解析表达式或验证字符串。
如果检测器仅仅搜索字符串 "eval",就容易产生误报。
类似地:
function evaluate(value) {
return value * 2;
}
module.exports = { evaluate };
这里的 "evaluate" 只是一个普通函数名称,并没有执行动态代码。
分析器应该识别实际语法结构,而不是把名称相似当作能力相同。
十五、识别 globalThis 的不同写法
JavaScript 可以通过 "globalThis" 访问全局对象。
以下代码表达了相关的全局操作:
eval(userInput);
globalThis.eval(userInput);
globalThis["eval"](userInput);
"Function" 构造器也有类似形式:
new Function("return 1");
new globalThis.Function("return 1");
new globalThis["Function"]("return 1");
这些写法可能对应不同的 AST 节点。
0.1.2 扩展了相应的识别逻辑和测试,覆盖更多显式写出的动态代码执行形式。
它也考虑了 "globalThis" 自身被局部变量遮蔽的情况。如果源文件声明了一个名为 "globalThis" 的局部变量,分析器不能仅凭名称就认定它是真正的全局对象。
十六、区分局部变量与全局 Function
例如:
const Function = value => value;
Function("ordinary text");
这里的 "Function" 是局部变量,并不是全局 "Function" 构造器。
类似情况也可能发生在函数参数中:
function run(Function) {
return Function("ordinary text");
}
或者导入绑定中:
import Function from "safe-module";
Function("ordinary text");
如果检测器把所有名为 "Function" 的调用都标记为动态代码执行,就会把这些情况错误地分类。
0.1.2 在 "src/ast-facts.js" 中扩展了保守的 AST 作用域检查,用于识别局部变量、参数和导入绑定对全局名称的遮蔽。
相关辅助函数包括:
- "bindingPatternHasName()"
- "lexicalDeclarationHasName()"
- "importStatementHasBinding()"
- "lexicalScopeHasBinding()"
- "varScopeHasBinding()"
- "functionScopeHasBinding()"
- "isNameShadowed()"
- "isUnshadowedGlobalThis()"
这不是完整的 JavaScript 名称解析器,但它比简单搜索关键词更精确。
十七、识别计算属性调用
JavaScript 支持点号调用:
cp.execSync("example");
也支持方括号形式:
cp["execSync"]("example");
对于 AST 来说,这两种写法可能对应不同节点类型。
0.1.2 扩展了 "callTarget()" 对可识别字符串字面量属性的处理,使分析器可以在特定条件下将调用归一化为:
object: cp
property: execSync
如果 "cp" 已经与 "child_process" 模块关联,这种信息就能帮助分析器识别潜在的进程创建操作。
但以下形式更复杂:
cp[methodName]("example");
如果 "methodName" 的值需要运行时才能确定,分析器不能自动假设它就是 "execSync"。
0.1.2 的改进针对可静态识别的属性,而不是承诺解析所有动态属性。
十八、导入 child_process 不等于执行系统命令
考虑:
import { execSync } from "node:child_process";
这段代码导入了一个能够启动系统命令的 API。
但是,导入本身并不能证明已经执行了命令。
真正的调用可能是:
execSync("some-command");
因此,需要区分两个事实:
1. 文件导入了具有特定能力的模块。
2. 文件中检测到了实际的进程创建调用。
0.1.2 将静态 "child_process" 导入作为能力信号记录,并将它与 "processSpawn" 分开。
例如,仅有导入的测试场景预期包含:
childProcess: true
processSpawn: false
这里有一个容易误解的地方:当前风险策略仍然可能因为存在 "child_process" 能力而将整体风险设为 "critical"。
这是一种保守的风险分类策略。
"critical" 并不证明文件已经执行了命令,也不证明代码具有恶意。
下游系统应该同时检查能力、实际操作及相关证据,而不是把整体风险标签当作完整的运行时行为描述。
十九、0.1.2 的主要变化
检测领域| 改进内容
动态代码执行| 覆盖更多全局 "eval" 和 "Function" 形式
计算属性| 识别部分字符串字面量方法调用
局部变量| 区分局部 "eval"、"Function" 与全局函数
函数参数| 增加参数遮蔽相关测试
globalThis| 检查全局对象名称被局部变量遮蔽的情况
对象与类方法| 避免把方法名称错误当作词法绑定
ES Module 导入| 为静态 "child_process" 导入添加能力信号
风险证据| 增加针对操作标志、风险等级和风险信号的回归测试
发布验证| 69/69 开发测试、通过的 CI,以及 8/8 定向消费者测试
这些改进的目标是让结构化事实更加准确,而不是让分析器声称自己了解所有程序行为。
---
第三部分:在 Termux 中复现 0.1.2 的回归测试
二十、创建独立的版本测试目录
前面的基础示例验证了路由、导入和环境变量。
现在,我们测试 0.1.2 特别关注的场景。
mkdir -p "$HOME/sentinel-ir-v012-check"
cd "$HOME/sentinel-ir-v012-check"
npm init -y
npm install --save-exact sentinel-ir@0.1.2
npm ls sentinel-ir
确认安装的是 "sentinel-ir@0.1.2"。
二十一、创建六个定向测试
以下测试会把源代码字符串交给分析器,而不是执行这些源代码。
创建文件:
cat > check-v012.js <<'NODE'
const assert = require("node:assert/strict");
const { analyzeAsync } = require("sentinel-ir");
const cases = [
{
name: "local Function is not the global constructor",
source: 'const Function = value => value; Function("ordinary text");',
risk: "low",
operations: { dynamicEval: false }
},
{
name: "global Function is dynamic code",
source: 'Function("return 1");',
risk: "critical",
operations: { dynamicEval: true }
},
{
name: "computed globalThis eval is detected",
source: 'globalThis["eval"]("input");',
risk: "critical",
operations: { dynamicEval: true }
},
{
name: "computed child_process method is detected",
source: 'const cp = require("child_process"); cp["execSync"]("example");',
risk: "critical",
operations: {
childProcess: true,
processSpawn: true
}
},
{
name: "ordinary object eval method is not global eval",
source: 'const parser = { eval(input) { return input; } }; parser.eval("text");',
risk: "low",
operations: { dynamicEval: false }
},
{
name: "static child_process import records capability, not a spawn",
source: 'import { execSync } from "node:child_process";',
risk: "critical",
operations: {
childProcess: true,
processSpawn: false
}
}
];
async function main() {
for (const item of cases) {
const result = await analyzeAsync(item.source, {
target: "smoke-test.js"
});
assert.equal(
result.analysisStatus,
"complete",
${item.name}: parsing should complete
);
assert.equal(
result.world.risk,
item.risk,
${item.name}: unexpected risk
);
for (const [operation, expected] of Object.entries(item.operations)) {
assert.equal(
result.facts.operations[operation],
expected,
${item.name}: operations.${operation}
);
}
console.log(PASS: ${item.name} (${result.world.risk}));
}
console.log(\n${cases.length}/${cases.length} smoke tests passed.);
}
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
NODE
运行测试:
node check-v012.js
如果所有断言都通过,最后一行应为:
6/6 smoke tests passed.
这些测试检查:
- 名为 "Function" 的局部变量不会自动被认定为全局构造器。
- 真正的全局 "Function()" 会被识别为动态代码执行。
- "globalThis["eval"]()" 会被识别。
- 与 "child_process" 关联的 "cp["execSync"]()" 会被识别为进程创建操作。
- 普通的 "parser.eval()" 不会仅因名称而被认定为全局 "eval"。
- 静态导入 "child_process" 会记录能力,但不会凭空证明进程已经启动。
最后一项尤其重要:测试预期 "processSpawn" 为 "false",但整体风险仍可能为 "critical"。这是当前风险策略的预期行为,而不是测试矛盾。
如果测试失败,不要直接修改预期值来让它通过。先记录错误、Node.js 版本和安装的包版本。
二十二、检查完整结构化报告
如果你不仅想检查风险等级,还想查看完整的紧凑 IR,可以创建另一个文件:
cat > inspect-v012.js <<'NODE'
const { analyzeAsync, compress } = require("sentinel-ir");
const code = `
const cp = require("child_process");
cp["execSync"]("example");
`;
async function main() {
const result = await analyzeAsync(code, {
target: "example.js"
});
console.log(JSON.stringify(compress(result), null, 2));
}
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
NODE
运行:
node inspect-v012.js
检查报告中的:
- "facts"
- "operations"
- "riskSignals"
- 与识别结果相关的证据
对于这个示例,预期可以看到与 "child_process" 相关的能力,以及被识别的进程创建操作。
具体行号和其他字段可能随输入变化。
重点是:检测结果应当来自解析后的代码结构,而不只是注释或字符串中出现了某个关键词。
二十三、在需要时运行完整开发测试套件
npm 发布包主要包含运行时文件和随包提供的 WebAssembly 语法文件,并不包含完整的开发测试套件。
如果你想检查源代码中的完整测试,需要单独克隆仓库。
cd "$HOME"
git clone gitlab.com
cd sentinel-ir
git checkout adf875a1502e3bcf7242bff85a32dcf62f023c07
npm ci
npm test
这里固定了对应 0.1.2 发布的提交,以避免把其他版本的代码误当作本次发布内容。
该发布版本的开发测试结果为:
69 tests passed
0 tests failed
需要注意,Android 上的可选原生 Tree-sitter 依赖可能与桌面 Linux 环境不同。
如果原生解析器无法初始化,前面针对已发布 npm 包的测试使用的是 "analyzeAsync()" 和 WebAssembly 路径。
不要把原生依赖安装失败与所有分析功能都不可用混为一谈,也不要在没有验证的情况下宣称所有 Android 设备都能顺利运行。
二十四、不同验证结果分别证明什么?
本次发布的验证记录包括以下几类检查:
1. 本地开发测试
- 69 项测试通过。
2. GitLab CI
- Pipeline:"#2964050242" (gitlab.com)
- 对应提交:"adf875a1"
- 三个 CI 任务全部成功。
3. 独立消费者测试
发布包 "sentinel-ir-0.1.2.tgz" 被安装到独立消费者目录中。
8 项定向测试通过,涉及变量遮蔽、导入绑定、方法名称、全局动态代码执行及 "globalThis" 访问。
4. 公共 npm registry
通过以下命令检查实际发布状态:
npm view sentinel-ir@0.1.2 version
npm view sentinel-ir dist-tags --json
这些检查回答的是不同的问题,不能相互替代。
本地测试通过,不代表公共包一定正确发布;CI 通过,也不代表每一种 Android 设备环境都已经被验证。
---
第四部分:常见问题与故障排查
二十五、Termux 软件仓库错误
如果执行 "pkg update" 时出现仓库不可用或镜像错误,可以运行:
termux-change-repo
在界面中选择可用的官方镜像,然后再次运行:
pkg update && pkg upgrade -y
请优先使用 Termux 官方文档中的仓库和镜像说明,不要因为某个镜像超时就复制来源不明的安装命令。
二十六、出现 node: command not found
重新检查软件包安装:
pkg update
pkg install nodejs -y
node --version
npm --version
如果软件包管理器本身无法正常工作,请先解决仓库问题。
二十七、Node.js 版本低于 20
运行:
pkg update && pkg upgrade -y
pkg install nodejs -y
node --version
如果版本仍然低于 20,请检查当前 Termux 仓库提供的版本。
不要盲目安装多个互相冲突的 Node.js 软件包。
二十八、npm install 出现原生 Tree-sitter 编译错误
Sentinel-IR 的原生 Tree-sitter 依赖是可选的。
如果原生依赖无法构建,可以在专门的测试目录中尝试跳过可选依赖:
cd "$HOME/sentinel-ir-termux-test"
rm -rf node_modules package-lock.json
npm install --save-exact --omit=optional sentinel-ir@0.1.2
这会跳过可选的原生解析器依赖,但不会跳过 WebAssembly 路径所需的常规 "web-tree-sitter" 依赖。
安装后重新检查:
npm ls sentinel-ir web-tree-sitter
然后重复 API 检查和 WebAssembly 初始化步骤。
注意:只在本教程创建的专用测试目录中执行清理命令。 不要在需要保留依赖的其他项目中随意删除 "node_modules"。
二十九、Cannot find module 'sentinel-ir'
检查当前目录和依赖:
cd "$HOME/sentinel-ir-termux-test"
npm ls sentinel-ir
如果没有安装,再运行:
npm install --save-exact sentinel-ir@0.1.2
如果仍然失败,请保留完整错误信息。
三十、WebAssembly 初始化失败
检查安装的版本和文件:
cd "$HOME/sentinel-ir-termux-test"
npm ls sentinel-ir web-tree-sitter
ls -lh node_modules/sentinel-ir/wasm/
确认包中包含 "tree-sitter-javascript.wasm"。
如果文件缺失或安装不完整,可以在专用测试目录中重新安装指定版本。
不要从不明网站下载其他 WebAssembly 二进制文件来替换它。
如果问题仍然存在,请记录 Node.js 版本、包版本和完整错误信息。
三十一、analysisStatus 为 incomplete
首先检查输入文件语法:
node --check sample.js
确认输入是受支持的 JavaScript,而不是超出当前支持范围的 TypeScript 或复杂 JSX。
不要将基于回退启发式规则生成的结果当作完整 AST 分析的等价结果。
三十二、预期路由或导入没有被识别
先确认分析的确实是教程中的示例:
cat sample.js
node analyze.js sample.js > report.json
然后检查:
cat report.json
如果示例与教程完全一致、分析状态为 "complete",但预期事实仍然缺失,请保留经过清理的最小示例及报告。
记录包版本、Node.js 版本、实际输出和预期输出。这些信息可以构成一个可复现的问题报告。
不要为了让测试通过而随意修改预期结果。
三十三、npm 无法访问 registry
先检查网络:
npm ping
npm view sentinel-ir@0.1.2 version
如果 registry 暂时不可用,可以稍后重试,或者切换 Wi-Fi 和移动网络。
在 registry 请求本身无法成功的情况下,不应直接将安装超时归因于分析器代码。
---
第五部分:安全地分享测试结果
三十四、不要直接公开完整项目报告
Sentinel-IR 的 JSON 报告可能包含:
- 导入的模块名称。
- 路由路径。
- 环境变量名称。
- 操作类型。
- 风险信号。
- 目标文件名。
这些信息可能暴露项目的内部结构。
即使报告没有主动提取秘密值,也不能假设报告天然适合公开。
在发布结果之前:
1. 检查报告中的每个字段。
2. 删除或泛化内部路由、文件名、客户信息和专有架构信息。
3. 不要未经许可发布他人的源代码或报告。
4. 优先使用本文提供的合成示例进行演示。
5. 明确说明测试的是合成示例还是自己有权检查的项目。
6. 记录准确的版本、Node.js 版本、命令、预期结果和实际结果。
7. 删除访问令牌、个人文件路径和其他敏感信息。
三十五、可复现测试报告模板
你可以将下面的模板用于 DEV Community、GitLab 讨论区或其他技术社区。
Title: Sentinel-IR 0.1.2 Termux smoke test
Device/OS: [Android version and device, if you want to share]
Termux source: [F-Droid or official GitHub]
Node.js: [output of node --version]
Sentinel-IR: 0.1.2
Input: [synthetic sample / my own authorized JavaScript file]
Command: node analyze.js sample.js
Expected:
analysisStatus=complete
route POST /upload
imports express and fs
environment variable PORT
Actual: [what really happened]
Result: [PASS / FAIL / INCOMPLETE]
Notes: [reproducible error or unexpected field, without secrets]
使用你自己的 DEV Community 或 GitLab 账户发布测试结果即可,不需要访问维护者账户。
一份有价值的问题报告应包含最小可公开示例、准确版本、预期行为、实际行为,以及分析状态是否完整。
---
最终检查清单
在结束之前,请确认以下事项。
- [ ] "node --version" 显示 Node.js 20 或更新版本。
- [ ] "npm ls sentinel-ir" 显示 "sentinel-ir@0.1.2"。
- [ ] "analyzeAsync"、"compress" 和 "initializeWasm" 已正确导出。
- [ ] WebAssembly 初始化成功。
- [ ] 示例文件通过语法检查。
- [ ] "node analyze.js sample.js" 成功生成报告。
- [ ] 报告的 "analysisStatus" 为 "complete"。
- [ ] 路由、导入和环境变量检查通过。
- [ ] 六项 0.1.2 定向 smoke tests 全部通过。
- [ ] 了解 "critical" 风险等级不等于已证明恶意或已执行命令。
- [ ] 了解 smoke test 不是完整安全认证。
如果某一步失败,不要隐藏失败结果。
记录错误、版本和环境信息。一个其他开发者可以复现的失败结果,通常比一句没有细节的“工具无法运行”更有价值。
---
最后的邀请
Sentinel-IR 的目标不是声称分析器可以理解所有代码,而是在分析开始之前,为下一步决策提供更紧凑、更容易检查的结构化事实。
如果你使用 Android 和 Termux 完成了测试,欢迎分享:
- 哪些结构被正确识别?
- 哪些事实缺失?
- 是否出现误报?
- 不同 Node.js 版本或 Android 环境是否产生了不同结果?
请尽量提供可复现的最小示例,而不是只发布截图。
让代码分析的结论可以被检查,让工具的限制也保持可见。
项目地址:
- npm:npmjs.com
- GitLab:gitlab.com
- 0.1.2 变更记录:gitlab.com
Sentinel-IR 0.1.2:在 Android Termux 上安装、分析并验证。
!Image description
2 reactions
Warmane on phone quick guide
I tried multiple times over the years to play on Warlame servers but I couldn't log in since warden disconnected me every time. Lately a guy on this sub made a post indicating it's plausible. It took me a few minutes to set it up and I was in! It took me a few minutes to set up controls and a day to get used to it, and I was skillcapped again.
Auction farming, playing rdf hc, chatting with friends, leveling, etc. It brought me much joy. Even though I don't play wow that much anymore, this was the most fun I had in a while. Right now I'll paste the vibecoded answer from opencode on how to set it up. If you're having difficulties I'd suggest you to install termux on the phone and to get opencode, it'll do everything for you, just send it the github link.
I'd suggest you to limit the framerate to 60, mine is at 35 even when I play on my desktop machine. I like old school, non shiny warcraft 3 tyoe of graphics.
If you have questions, ask in the comments so everyone can make use of it. I don't reply to messages. Here's the guide:
Title: Play WoW 3.3.5a (Warmane) on Android — step-by-step, with background play
Body:
A lot of people can get WoW running on Android but then it closes the moment they switch apps. I'm sharing an unofficial BannerHub build that keeps WoW running and connected in the background, plus the full setup.
Part 1 — Download and install the app
1. Open the repo: codxbre/wow-mobile-bannerhub
2. Go to Releases → v1.0 → download BannerHub-v3.8.1-Normal-BG2.apk.
3. Install it. If you already have BannerHub v3.8.1 Normal, it updates straight over it. If you have a different BannerHub/GameHub variant, uninstall that first.
4. Open the app and allow notifications. When a game is running you'll see a "Game running" notification — that's the background service keeping your session alive.
Part 2 — Get WoW from your PC (don't download it on the phone)
Downloading the client directly on the phone usually gives you a bare game with no addons or settings. Copy your existing folder instead:
1. On your PC, find your WoW 3.3.5a folder (the one with Wow.exe, Data, Interface, WTF).
2. Copy the whole folder to your phone at:
/storage/emulated/0/Download/World of Warcraft 3.3.5a/
3. Keep Interface/AddOns and WTF — those are your addons and settings.
4. Don't rename Wow.exe.
Part 3 — Add the game
1. Open BannerHub and add/import the game.
2. Pick Wow.exe in that folder.
3. Launch.
Part 3b — Controls, keybinds & trackpad
Quick walkthrough of the in-game Controls tab — on-screen buttons, keybinds, mouse/trackpad gestures, and the virtual controller:
youtube.com
BannerHub uses the same Controls layout as Winlator/GameHub, so everything in the video applies.
Part 4 — If the game won't start
1. Open the game's PC Game Settings.
2. Set GPU Driver → System Driver.
3. Launch again.
4. Still stuck? Open BannerHub's component/firmware section, update the firmware/container, and retry.
Part 5 — If you hear sound but the screen is black
1. Close the game.
2. Open World of Warcraft 3.3.5a/WTF/Config.wtf in a text editor.
3. Make sure these lines are there (add them if missing):
SET gxWindow "1"
SET gxMaximize "1"
SET gxResolution "1280x720"
4. Save and launch again. Windowed mode at the container's real resolution fixes the black screen.
Part 6 — Playing in the background
- Leave the "Game running" notification alone while you play.
- On Xiaomi/HyperOS also set Settings → Apps → BannerHub → Battery → No restrictions, and allow background data.
- Now you can switch apps or open BannerHub's settings and WoW stays connected.
Part 7 — If nothing works: let an AI agent fix it
If you've tried everything and the game still fails, you can install a terminal and an AI coding agent on the phone and let it diagnose the setup.
1. Install Termux from F-Droid (f-droid.org) or the GitHub releases (github.com/termux/termux-app/releases). Don't use the Play Store version — it's outdated.
2. Open Termux and run:
pkg update -y && pkg upgrade -y
pkg install -y curl git
termux-setup-storage
curl -fsSL opencode.ai | bash
opencode
3. In opencode, run /connect and choose a provider with a free tier — for example Google (free API key from Google AI Studio) or OpenRouter (free models). Paste the key, then run /models and pick a model marked free.
4. Paste this prompt (fill in the brackets):
I'm on Android (Termux) trying to run World of Warcraft 3.3.5a (Warmane) through
BannerHub v3.8.1 Normal (modified APK from
codxbre/wow-mobile-bannerhub).
My device: [phone model, Android version, GPU].
Problem: [game won't start / black screen with sound / disconnects in background / other].
What I already tried: [GPU Driver = System Driver, config.wtf windowed 1280x720,
installed the background APK, battery = No restrictions].
Please:
1. Find and read my logs (logcat, wine.log, f7f8-debug.log) under
/storage/emulated/0 and /data/data/com.termux/files/home.
2. Diagnose the actual cause.
3. Fix it step by step. If the APK needs patching, build a new one in the cloud
(e.g. GitHub Actions) and put it in /storage/emulated/0/Download.
4. If you need more information, ask me.
5. Follow its steps and try the game again.
Notes
- This is an unofficial community build. No game files are included — use your own WoW 3.3.5a client.
- All credit to The412Banner (BannerHub) and the GameHub team.
- Tested with Warmane Icecrown 3.3.5a on a Redmi/Adreno device.
37 points · 16 comments
Sentinel-IR on Android: Install It in Termux Mobile and Verify the Output, Step by Step
!Image description
From a fresh Termux terminal to a real, inspectable JavaScript analysis report. No desktop computer, no API key, no AI account required.
> What this guide does: installs the published sentinel-ir@0.1.1 package, initializes its bundled WebAssembly parser, analyzes a tiny JavaScript example, checks expected results, and saves a JSON report. It then shows how to analyze one JavaScript file you own and how to share sanitized findings under your own account.
>
> What it does not do: it does not prove that a program is secure, scan an entire repository, analyze TypeScript/JSX reliably, or send source code to an LLM. The 0.1.1 release was tested in Termux. This walkthrough uses the published package's documented API and includes troubleshooting because Android and Termux installations can differ.
Thanks for support..
Release: "Sentinel-IR-MCP v0.2.2 on GitLab" (gitlab.com)
Package: "sentinel-ir-mcp@0.2.2 on npm" (npmjs.com)
⚡ The 20-Second Version
You can run a small JavaScript structural analyzer from an Android phone. Termux gives Android a Linux-style terminal, Node.js runs JavaScript, and Sentinel-IR turns a source string into a compact JSON report with facts such as recognized routes, imports, environment variables, operations, and risk signals.
The point of this tutorial is simple: do not take my word for it. Install the exact published version, run the sample, and inspect the output yourself. If you find a problem, report it from your account, with enough detail for someone else to reproduce it.
Yes, this is the kind of project you can experiment with from bed instead of spending the entire evening scrolling. Your phone is not a magic workstation, and not every idea becomes a product. But it can be enough to run a real, testable experiment.
🗺️ Quick Navigation
Tap any link below to jump directly to that section. At the end of each phase, use Contents to return here or Next to continue without scrolling back to the top.
- [The 20-Second Version](#the-20-second-version)
- [How to read the visual markers](#how-to-read-the-visual-markers)
- [Before We Start: What You Need](#before-we-start-what-you-need)
- [Phase 0: Open Termux](#phase-0-open-termux-and-understand-the-terminal)
- [Phase 1: Update Termux](#phase-1-update-termux-packages)
- [Phase 2: Install Node.js](#phase-2-install-nodejs-and-npm)
- [Phase 3: Create a test folder](#phase-3-create-a-clean-test-folder)
- [Phase 4: Install Sentinel-IR](#phase-4-install-the-exact-published-release)
- [Phase 5: Check the API](#phase-5-check-that-the-public-api-exists)
- [Phase 6: Initialize WebAssembly](#phase-6-initialize-the-bundled-webassembly-parser)
- [Phase 7: Create the sample](#phase-7-create-a-harmless-javascript-sample)
- [Phase 8: Create the analysis script](#phase-8-create-a-small-analysis-program)
- [Phase 9: Run the analysis](#phase-9-run-the-analysis-and-save-a-report)
- [Phase 10: Verify the findings](#phase-10-verify-the-findings-instead-of-just-looking-at-a-json-blob)
- [Phase 11: Try your own file (optional)](#phase-11-try-a-javascript-file-of-your-own-optional)
- [Option A: File inside Termux](#option-a-the-file-is-already-inside-termux)
- [Option B: File in Android Downloads](#option-b-the-file-is-in-android-downloads)
- [Phase 12: Understand the result](#phase-12-understand-analysisstatus)
- [Phase 13: Share findings safely](#phase-13-share-a-result-without-leaking-your-code)
- [Troubleshooting](#troubleshooting-if-something-goes-wrong)
- [Repository errors](#repository-errors-when-running-pkg-update)
- [node: command not found](#node-command-not-found)
- [Node.js is older than version 20](#nodejs-is-older-than-version-20)
- [Native build warnings or errors](#npm-install-shows-native-build-warnings-or-errors)
- [Cannot find module 'sentinel-ir'](#cannot-find-module-sentinel-ir)
- [WebAssembly initialization failed](#webassembly-initialization-failed)
- [analysisStatus is incomplete](#analysisstatus-is-incomplete)
- [Expected route or import is missing](#the-expected-route-or-import-is-missing)
- [npm cannot reach the registry](#npm-cannot-reach-the-registry)
- [What Counts as a Successful Finish?](#what-counts-as-a-successful-finish)
- [One Final Invitation](#one-final-invitation)
How to read the visual markers
- 🟦 DO THIS: copy the command block into Termux and press Enter.
- ✅ EXPECTED RESULT: compare your terminal output with this example.
- ⚠️ IF THIS FAILS: stop at that step and use the linked troubleshooting section.
- 🧪 OPTIONAL: skip it on your first run if you only want to verify the package.
Do one step at a time. Continue only when the expected result makes sense. The coloured code syntax and headings are part of DEV.to's normal rendering, not evidence that a test passed.
📦 Before We Start: What You Need
- An Android phone supported by Termux.
- A working internet connection for the initial package downloads.
- A little free storage. Node.js and npm dependencies need room, so do not start with your storage completely full.
- Around 10 to 20 minutes if package downloads behave. Slow mirrors or older installations can take longer.
- No root access, no API key, no OpenAI account, and no desktop computer.
Use the official Termux sources. The maintainers document installation through F-Droid and the official GitHub repository. Avoid random APK files from chat groups or download sites. If you already have Termux installed, do not uninstall it casually: builds from different sources may use different signing keys. Update the installation you already have unless you have a specific reason to switch.
Official project references:
- Sentinel-IR npm package, version 0.1.1
- Sentinel-IR README for tag v0.1.1
- Sentinel-IR source tag v0.1.1
- Official Termux installation instructions
---
🧭 Phase 0: Open Termux and understand the terminal
Open Termux. You should see a terminal prompt and a blinking cursor. Type or paste a command, then press Enter. Commands in this guide should be run inside Termux unless a step explicitly says otherwise.
A few phone-specific tips:
- Paste one code block at a time. Wait for the prompt to return before pasting the next block.
- If you see a long stream of installation text, that is normal. Read the last few lines if a command fails.
- Do not paste a line that begins with a prompt character such as $. The $ in documentation usually means “type the command after this symbol”. The blocks below omit it.
- If Android closes Termux in the background, reopen it and run the last command again. Do not assume a command completed just because you switched apps.
- You do not need to grant access to all shared phone storage for the first test. We will create everything inside Termux's private home directory.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 1](#phase-1-update-termux-packages)
🧭 Phase 1: Update Termux packages
Run:
🟦 DO THIS · Run in Termux
pkg update && pkg upgrade -y
pkg update refreshes the package lists. pkg upgrade -y updates installed packages and automatically accepts the package manager's normal confirmation prompt.
> ✅ IF IT WORKS: if the command finishes and returns to the prompt, continue.
>
> ⚠️ IF THIS FAILS: if it stops with a repository or mirror error, jump to [Troubleshooting: repository errors](#repository-errors-when-running-pkg-update) below.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 2](#phase-2-install-nodejs-and-npm)
🧭 Phase 2: Install Node.js and npm
Sentinel-IR requires Node.js 20 or newer. npm normally comes with the Termux Node.js package.
🟦 DO THIS · Run in Termux
pkg install nodejs -y
Now check both tools:
🟦 DO THIS · Run in Termux
node --version
npm --version
Node should print a version number such as v20.x, v22.x, v24.x, or newer. The exact current version depends on the Termux repository and the day you install it. npm should also print a version number.
Use this extra check to verify the Node major version numerically:
🟦 DO THIS · Run in Termux
node -e "const major = Number(process.versions.node.split('.')[0]); console.log('Node.js:', process.version); if (major < 20) { console.error('Sentinel-IR requires Node.js 20 or newer'); process.exit(1); } console.log('PASS: Node.js version is supported');"
✅ EXPECTED RESULT
PASS: Node.js version is supported
> ⚠️ IF THIS FAILS: if Node is below 20, do not continue and hope for the best. Update Termux packages and check the available Node package again. See [Troubleshooting: old Node.js](#nodejs-is-older-than-version-20).
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 3](#phase-3-create-a-clean-test-folder)
🧭 Phase 3: Create a clean test folder
Keep the experiment separate from your photos, downloads, and other projects.
🟦 DO THIS · Run in Termux
mkdir -p "$HOME/sentinel-ir-termux-test"
cd "$HOME/sentinel-ir-termux-test"
pwd
The final command should print a path inside Termux's home directory, usually beginning with /data/data/com.termux/files/home/.
Every file created in the remaining steps will live in this folder. You can return to it later with:
🟦 DO THIS · Run in Termux
cd "$HOME/sentinel-ir-termux-test"
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 4](#phase-4-install-the-exact-published-release)
🧭 Phase 4: Install the exact published release
First, create a minimal local npm project:
🟦 DO THIS · Run in Termux
npm init -y
Install the exact release covered by this guide, rather than whichever version might be published as latest in the future:
🟦 DO THIS · Run in Termux
npm install --save-exact sentinel-ir@0.1.1
This package has a regular web-tree-sitter dependency and optional native Tree-sitter dependencies. The normal install may try to install those optional native packages too. Our test will explicitly use the bundled WebAssembly parser through analyzeAsync(), which is the intended path when native parser packages are unavailable.
Check that npm installed the exact version:
🟦 DO THIS · Run in Termux
npm ls sentinel-ir
You should see sentinel-ir@0.1.1 in the dependency tree. The package is installed locally in this test folder. You do not need a global npm installation and should not use sudo in Termux.
You can independently ask the public registry which version it serves:
🟦 DO THIS · Run in Termux
npm view sentinel-ir@0.1.1 version
✅ EXPECTED RESULT
0.1.1
> ⚠️ IF THIS FAILS: if this command says it cannot reach the registry, that is a network or registry access issue, not evidence that the analyzer failed. Check your connection and use the troubleshooting section.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 5](#phase-5-check-that-the-public-api-exists)
🧭 Phase 5: Check that the public API exists
Run this block exactly as shown:
🟦 DO THIS · Run in Termux
node - <<'NODE'
const sentinel = require('sentinel-ir');
for (const name of ['analyzeAsync', 'compress', 'initializeWasm']) {
console.log(`${name}: ${typeof sentinel[name]}`);
if (typeof sentinel[name] !== 'function') {
console.error(`FAIL: missing function ${name}`);
process.exitCode = 1;
}
}
if (!process.exitCode) {
console.log('PASS: expected Sentinel-IR functions are exported');
}
NODE
The three lines should end in function, followed by:
✅ EXPECTED RESULT
PASS: expected Sentinel-IR functions are exported
> ⚠️ IF THIS FAILS: if you see Cannot find module, check that your terminal is still in the test directory and run npm ls sentinel-ir again. If the installed version is not 0.1.1, return to Phase 4.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 6](#phase-6-initialize-the-bundled-webassembly-parser)
🧭 Phase 6: Initialize the bundled WebAssembly parser
This is a direct check of the WebAssembly initialization path, before we analyze a file.
🟦 DO THIS · Run in Termux
node - <<'NODE'
const { initializeWasm } = require('sentinel-ir');
initializeWasm()
.then(() => {
console.log('PASS: Sentinel-IR WebAssembly parser initialized');
})
.catch((error) => {
console.error('FAIL: WebAssembly initialization failed');
console.error(error);
process.exitCode = 1;
});
NODE
✅ EXPECTED RESULT
PASS: Sentinel-IR WebAssembly parser initialized
> ⚠️ IF THIS FAILS: if initialization fails, do not quietly move to the next step. See [Troubleshooting: WebAssembly initialization](#webassembly-initialization-failed). The usual checks are whether the package finished installing, whether the packaged WASM file exists, and whether the exact version is installed.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 7](#phase-7-create-a-harmless-javascript-sample)
🧭 Phase 7: Create a harmless JavaScript sample
We will analyze text that looks like a tiny Express-style server. Sentinel-IR analyzes the source text; this guide does not run the server. You do not need to install Express because the code is only the input to the parser.
Create the sample:
🟦 DO THIS · Run in Termux
cat > sample.js <<'JS'
const express = require("express");
const fs = require("fs");
const app = express();
app.post("/upload", (req, res) => {
fs.writeFileSync("/tmp/upload", req.body);
res.end();
});
app.listen(process.env.PORT);
JS
Check the file was created:
🟦 DO THIS · Run in Termux
cat sample.js
You should see the JavaScript block you just pasted. You can also check its syntax with Node.js without executing the server:
🟦 DO THIS · Run in Termux
node --check sample.js
If the syntax check succeeds, Node normally prints nothing and returns to the prompt. If it reports a syntax error, recreate the file using the full cat block above. Be careful not to include the Markdown code fences in the file.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 8](#phase-8-create-a-small-analysis-program)
🧭 Phase 8: Create a small analysis program
Now create a reusable script. It reads one JavaScript file, passes the text to analyzeAsync(), compresses the result, and prints JSON. It does not execute the input file, call an LLM, or upload the input.
🟦 DO THIS · Run in Termux
cat > analyze.js <<'JS'
const fs = require('node:fs/promises');
const path = require('node:path');
const { analyzeAsync, compress } = require('sentinel-ir');
async function main() {
const inputPath = process.argv[2];
if (!inputPath) {
console.error('Usage: node analyze.js <file.js>');
process.exitCode = 1;
return;
}
const source = await fs.readFile(inputPath, 'utf8');
const ir = await analyzeAsync(source, {
// Use only the filename in the report, not the full private device path.
target: path.basename(inputPath),
});
const report = compress(ir);
console.log(JSON.stringify(report, null, 2));
if (report.analysisStatus !== 'complete') {
console.error(
'WARNING: analysisStatus is not complete. Do not treat this result as a complete structural analysis.'
);
process.exitCode = 2;
}
}
main().catch((error) => {
console.error('ERROR: analysis could not finish.');
console.error(error && error.stack ? error.stack : error);
process.exitCode = 1;
});
JS
Check the wrapper's own syntax:
🟦 DO THIS · Run in Termux
node --check analyze.js
Again, a successful syntax check normally prints nothing. This tests the small wrapper, not Sentinel-IR's accuracy.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 9](#phase-9-run-the-analysis-and-save-a-report)
🧭 Phase 9: Run the analysis and save a report
Run:
🟦 DO THIS · Run in Termux
node analyze.js sample.js > report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
The JSON is saved in report.json, not lost in a wall of terminal output. The exit code means:
- 0: the script produced a result whose analysisStatus is complete.
- 2: a result was produced, but the analysis status was not complete. Read the warning and do not count this as a successful complete analysis.
- 1: the wrapper could not finish, for example because it could not read the input or initialize the parser.
Display the report:
🟦 DO THIS · Run in Termux
cat report.json
The report is JSON. Its exact formatting and some values can vary with the input, but for the supplied valid JavaScript sample you should expect structural facts resembling these:
- analysisStatus should be complete.
- facts.ast should be true.
- facts.routes should include POST /upload.
- facts.imports should include express and fs.
- facts.env should include PORT.
- The report should include recognized operations and risk signals related to the route and file write.
The report's risk estimate is not a verdict that this example is safe or unsafe. The sample deliberately includes an HTTP route and a filesystem write so there is something tangible to inspect.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 10](#phase-10-verify-the-findings-instead-of-just-looking-at-a-json-blob)
🧭 Phase 10: Verify the findings instead of just looking at a JSON blob
Run an automatic check against the results we expect from the sample:
🟦 DO THIS · Run in Termux
node - <<'NODE'
const report = require('./report.json');
const failures = [];
if (report.analysisStatus !== 'complete') {
failures.push(`analysisStatus expected complete, got ${report.analysisStatus}`);
}
if (report.facts?.ast !== true) {
failures.push('facts.ast expected true');
}
if (!Array.isArray(report.facts?.routes) || !report.facts.routes.includes('POST /upload')) {
failures.push('expected route POST /upload was not found');
}
if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('express')) {
failures.push('expected import express was not found');
}
if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('fs')) {
failures.push('expected import fs was not found');
}
if (!Array.isArray(report.facts?.env) || !report.facts.env.includes('PORT')) {
failures.push('expected environment variable PORT was not found');
}
if (failures.length) {
console.error('FAIL: sample analysis did not match expectations');
for (const failure of failures) console.error(`- ${failure}`);
process.exitCode = 1;
} else {
console.log('PASS: the sample produced the expected structural facts');
}
NODE
✅ EXPECTED RESULT
PASS: the sample produced the expected structural facts
This is a reproducible smoke test. It shows that this installed package can parse this particular sample and return the facts checked by the script. It is not a broad benchmark, a full test suite, or proof that every JavaScript pattern is recognized correctly.
You can also print the most useful fields without dumping the whole report:
🟦 DO THIS · Run in Termux
node - <<'NODE'
const r = require('./report.json');
console.log('analysisStatus:', r.analysisStatus);
console.log('routes:', r.facts.routes);
console.log('imports:', r.facts.imports);
console.log('environment variables:', r.facts.env);
console.log('operations:', r.facts.operations);
console.log('risk signals:', r.facts.riskSignals);
NODE
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 11](#phase-11-try-a-javascript-file-of-your-own-optional)
🧭 Phase 11: Try a JavaScript File of Your Own · 🧪 OPTIONAL
You have already tested the package with a known sample. Only now try your own input.
Only analyze code you own or are authorized to inspect. Start with one .js file, not an entire repository. Sentinel-IR analyzes one JavaScript file at a time; it does not combine calls or data flow across files.
📁 Option A: The file is already inside Termux
Copy your file into the test directory, or run the analyzer with its path:
🟦 DO THIS · Run in Termux
node analyze.js ./your-file.js > your-file-report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
Replace your-file.js with the real filename. If you need to keep a report, give it a different name so you do not overwrite report.json.
📱 Option B: The file is in Android Downloads
For this optional path, grant Termux shared-storage access only if you need it:
🟦 DO THIS · Run in Termux
termux-setup-storage
Android may show a permission dialog. Approve it if you want Termux to read your shared files. Then list Downloads:
🟦 DO THIS · Run in Termux
ls "$HOME/storage/downloads"
Copy one JavaScript file into the private test folder, replacing example.js with its exact filename:
🟦 DO THIS · Run in Termux
cp "$HOME/storage/downloads/example.js" "$HOME/sentinel-ir-termux-test/your-file.js"
cd "$HOME/sentinel-ir-termux-test"
node analyze.js your-file.js > your-file-report.json
rc=$?
printf 'Analyzer exit code: %s\n' "$rc"
💡 TIP: if the filename contains spaces, keep the quotation marks. If the file is not listed in Downloads, check the correct folder name with ls. You do not need to enable this permission for the earlier sample test.
A file can be JavaScript-shaped but still use syntax that Sentinel-IR does not support. The package currently targets JavaScript, including CommonJS and ESM. It does not claim general TypeScript, JSX-heavy, or other-language support.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 12](#phase-12-understand-analysisstatus)
🧭 Phase 12: Understand analysisStatus
This field is one of the most important parts of the output.
- complete means AST extraction succeeded and the source parsed without syntax errors. It does not mean every security issue was found.
- incomplete means AST extraction was unavailable or the source did not parse cleanly. The output may rely on text-based fallback heuristics, which can be wrong in either direction.
> ⚠️ IF THIS FAILS: if a report is incomplete, do not write “Sentinel-IR cleared this file” or “the code is safe”. Instead, report that the result was incomplete and explain which input you used. Depending on the file, check the syntax, make sure it is plain supported JavaScript, and try a smaller reproducible example.
Even complete has strict limits:
1. It is a syntax-based structural report, not full semantic analysis.
2. It examines one file at a time.
3. It may not resolve aliases, computed properties, or behavior passed between modules.
4. It does not prove the application is secure.
5. It reduces some untrusted text passed onward, but it does not eliminate prompt injection.
6. It does not run your app or decide what an AI agent should do.
Do not treat values such as world.confidence as calibrated probabilities. They are configuration or metadata fields, not a validated guarantee that the output is correct.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 13](#phase-13-share-a-result-without-leaking-your-code)
🧭 Phase 13: Share a result without leaking your code
Now for the part that matters if you want to publish a finding.
The JSON report may contain names of imported packages, route paths, environment-variable names, operation names, risk signals, and the target filename you supplied. Those can reveal internal architecture. Even if a secret value is not intentionally extracted, never assume any generated report is automatically safe to publish.
Before posting:
1. Open the report and review every field.
2. Remove or generalize private route names, internal package names, filenames, customer information, and anything that reveals a secret or proprietary design.
3. Do not publish private source code or a report from somebody else's code without permission.
4. Prefer the small synthetic sample from this guide when demonstrating basic behavior.
5. State clearly whether you tested the synthetic sample or your own project.
6. Include the exact version, Node version, command, expected result, actual result, and error text if something failed. Remove access tokens and personal filesystem paths.
7. Do not claim that a single smoke test proves the analyzer is secure or accurate in all cases.
You can check the environment before writing your report:
🟦 DO THIS · Run in Termux
node --version
npm --version
npm ls sentinel-ir
Here is a report template you can adapt for DEV Community, GitLab, a discussion thread, or your own blog:
📝 COPY THIS TEMPLATE AND FILL IT IN
Title: Sentinel-IR 0.1.1 Termux smoke test
Device/OS: [Android version and device, if you want to share]
Termux source: [F-Droid or official GitHub]
Node.js: [output of node --version]
Sentinel-IR: 0.1.1
Input: [synthetic sample / my own authorized JavaScript file]
Command: node analyze.js sample.js
Expected: analysisStatus=complete, route POST /upload, imports express and fs, env PORT
Actual: [what really happened]
Result: [PASS / FAIL / INCOMPLETE]
Notes: [reproducible error or unexpected field, without secrets]
Use your own DEV Community or GitLab account to publish your own test result. You do not need access to the maintainer's account. A useful bug report includes a minimal input that you are allowed to share, the exact version, what you expected, what happened, and whether analysisStatus was complete.
⬆️ [Contents](#quick-navigation) · ➡️ [Next: Troubleshooting](#troubleshooting-if-something-goes-wrong)
🧰 Troubleshooting: If Something Goes Wrong
Repository errors when running pkg update
> ⚠️ IF THIS FAILS: if Termux reports that a repository is unreachable or under maintenance, check your connection and change the Termux mirror:
🟦 DO THIS · Run in Termux
termux-change-repo
Choose an available official mirror in the interface, then run:
🟦 DO THIS · Run in Termux
pkg update && pkg upgrade -y
The Termux maintainers document repository and mirror fixes in their Package Management guide. Do not paste commands from unrelated download sites just because a mirror timed out.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
node: command not found
Install Node.js again from Termux:
🟦 DO THIS · Run in Termux
pkg update
pkg install nodejs -y
node --version
npm --version
> ⚠️ IF THIS FAILS: if the package manager itself is broken, resolve the repository issue first.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
Node.js is older than version 20
Run:
🟦 DO THIS · Run in Termux
pkg update && pkg upgrade -y
pkg install nodejs -y
node --version
> ⚠️ IF THIS FAILS: if the installed version is still below 20, do not continue with this release. Check the available packages in your Termux repository and follow the official Termux package guidance. Do not install two alternative Node packages blindly; they can conflict.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
npm install shows native build warnings or errors
Sentinel-IR's native Tree-sitter packages are optional. This guide uses the bundled WASM parser, so retry the installation without optional dependencies:
🟦 DO THIS · Run in Termux
cd "$HOME/sentinel-ir-termux-test"
rm -rf node_modules package-lock.json
npm install --save-exact --omit=optional sentinel-ir@0.1.1
This deliberately skips optional native parser packages. It does not skip the regular web-tree-sitter dependency needed by the WASM path. Then repeat Phase 5 and Phase 6.
Only run the cleanup command in the dedicated test folder created by this guide. Do not run rm -rf node_modules in a project where you need to preserve the current installation.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
Cannot find module 'sentinel-ir'
Check your location and installation:
🟦 DO THIS · Run in Termux
cd "$HOME/sentinel-ir-termux-test"
npm ls sentinel-ir
> ⚠️ IF THIS FAILS: if it is missing, install the pinned release again:
🟦 DO THIS · Run in Termux
npm install --save-exact sentinel-ir@0.1.1
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
WebAssembly initialization failed
First verify the package and WASM file are present:
🟦 DO THIS · Run in Termux
cd "$HOME/sentinel-ir-termux-test"
npm ls sentinel-ir web-tree-sitter
ls -lh node_modules/sentinel-ir/wasm/
The published package should include tree-sitter-javascript.wasm. If the folder or file is missing, retry the install in the test directory. Check that the install finished and that the package version is 0.1.1.
> ⚠️ IF THIS FAILS: if it still fails, keep the complete error message and your Node version. Do not replace the WASM file with an unrelated binary from a random website.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
analysisStatus is incomplete
The package may have been unable to perform AST extraction, or the file did not parse cleanly. Check:
🟦 DO THIS · Run in Termux
node --check sample.js
Remember that the basic test expects JavaScript. TypeScript, JSX-heavy syntax, or other programming languages are outside the documented support claim. Do not treat fallback results as an equivalent structural parse.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
The expected route or import is missing
First confirm that you are analyzing the sample from this guide, not another file:
🟦 DO THIS · Run in Termux
cat sample.js
node analyze.js sample.js > report.json
Then inspect report.json. If the sample is exactly as shown, analysisStatus is complete, and the expected fact is still absent, preserve a sanitized copy of the sample and report the mismatch with package version and Node version. That is a useful reproducible issue. Do not change the expected output just to force a pass.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
npm cannot reach the registry
Check connectivity, then retry:
🟦 DO THIS · Run in Termux
npm ping
npm view sentinel-ir@0.1.1 version
> ⚠️ IF THIS FAILS: if the registry is temporarily unavailable on your connection, retry later or switch between Wi-Fi and mobile data. Do not post an installation timeout as an analyzer defect until the registry request itself works.
⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong)
✅ What Counts as a Successful Finish?
By the end, all of these should be true:
- node --version is at least 20.
- npm ls sentinel-ir shows version 0.1.1.
- The expected exported functions are present.
- initializeWasm() finishes successfully.
- node analyze.js sample.js writes report.json.
- The report says analysisStatus: "complete" for the sample.
- The verification script prints PASS: the sample produced the expected structural facts.
- You understand that this is a smoke test, not a security certification.
✅ IF ALL CHECKS PASS: you have reproduced a small test of the published package on your phone. That is already useful: you did not need to trust a screenshot or a claim, because you ran the commands and inspected the output yourself.
> ⚠️ IF THIS FAILS: if a check fails, that is not a personal failure. Keep the error, report the environment, and share only sanitized reproducible details. A failed reproducible test is more useful than a vague statement that something “doesn't work”.
⬆️ [Contents](#quick-navigation) · ➡️ [Final invitation](#one-final-invitation)
🚀 One Final Invitation
Try it with the sample first. Then, if you have a JavaScript file you own and are comfortable inspecting, try that one. Check whether the facts match what the code actually contains. Look for missing facts and false positives. Tell me what you found, including the parts that did not work.
This is a small structural analyzer, not an oracle. The interesting part begins when more people can run the same experiment, compare observations, and challenge the claims with evidence.
Built and released from a phone-friendly workflow. Verified by your own terminal.
3 reactions
Mentions
Try Linux on Android - Termux XFCE Installation (for beginners) Requirements | Resource | Amount | |----------------|--------| | RAM | 4GB | | Storage | 3GB | | Internet Data | 450MB | APK - Termux: termux/termux-app - Termux X11: termux/termux-x11 Permissions - Notification: important to edit preferences and to stop the app - Storage: necessary to read-write files Installation 1. Open Termux, then allow storage access: termux-setup-storage 2. Change repository: termux-change-repo 3. Update & upgrade: pkg update && pkg upgrade -y 4. Hide welcome message: touch ~/.hushlogin 5. Add repositories: pkg in tur-repo x11-repo termux-x11-nightly 6. Install the essentials: pkg in xfce4 ffmpeg ffmpegthumbnailer mousepad ristretto neofetch firefox vlc-qt xfce4-whiskermenu-plugin 7. Start the desktop: termux-x11 :0 -xstartup "dbus-launch --exit-with-session xfce4-session" 8. Open Termux X11 Enjoy Linux!
How to Build Your Own Smart AI Assistant Using Only Your Android Phone (Termux + Python) How to Build Your Own Smart AI Assistant Using Only Your Android Phone (Termux + Python) Have you ever wanted to build your own AI assistant but assumed you needed an expensive computer, powerful graphics card or years of programming experience? What if I told you that you could build a working AI assistant using nothing more than your Android phone? You don't need a laptop. You don't need an expensive development environment. You don't even need to be an experienced programmer. With Termux, Python and an AI API, you can create a personal AI assistant directly from your Android device. In this tutorial, we're going to build one step by step. But we're not going to stop at creating a basic chatbot that simply accepts a question and returns an answer. We'll build an assistant that has: - Its own personality and instructions. - The ability to hold conversations. - Short-term conversational memory. - A customizable name. - The ability to remember previous messages during a session. - Commands to reset conversations and exit. - Basic error handling. - A simple terminal interface. By the end, you'll understand how the different parts work and how to extend the project into something more advanced. You can follow this tutorial even if you've never built an AI application before. Let's get started. 1. First, Understand What We're Building Before installing anything, let's understand how our assistant will work. An AI assistant generally has several components. 1. The interface This is where you communicate with your assistant. In our project, the interface will be the Termux terminal. 2. The programming language We'll use Python to handle the application's logic. Python will receive your messages, organize conversation history and communicate with the AI service. 3. The AI model This is the component responsible for understanding questions and generating intelligent responses. Instead of training a massive AI model ourselves, we'll connect our application to an existing model through an API. 4. Memory We'll create a system that keeps previous messages during the conversation. This allows the assistant to understand follow-up questions. For example: You: My name is Daniel. Assistant: Nice to meet you, Daniel! You: What is my name? Assistant: Your name is Daniel. Without conversation history, the assistant might not understand the second question. 5. Personality and instructions We'll give our assistant specific instructions about how it should communicate, explain things and respond to users. This is what makes it behave more like a personal assistant rather than a generic chatbot. How everything connects Our application will follow this process: 1. You enter a message. 2. Python receives the message. 3. Python adds it to the conversation history. 4. The application sends the conversation to the AI model. 5. The AI generates a response. 6. Python displays the response. 7. The conversation history is updated. That's the basic architecture. An important distinction: Termux and Python will run on your phone, but the AI model will run on a remote server. Therefore, this first version requires an internet connection. Your phone is building and controlling the assistant, not performing the expensive AI inference itself. 2. What You Need Before Starting You only need three main things. A. An Android phone Any reasonably modern Android device supported by the current Termux release should be suitable for this lightweight project. You don't need a flagship phone. Our application will not be running a massive language model locally. B. Termux Termux is an Android terminal emulator and Linux environment. It allows you to run programming languages, install development packages and execute commands directly from your phone. Download it from an official distribution linked by the Termux project. - Termux website: termux.dev - Official GitHub repository: termux/termux-app Avoid mixing Termux installations from different distribution sources. Its companion applications and plugins should come from the same source. C. An AI API key We'll use an AI API to connect our Python application to an existing language model. An API allows one application to communicate with another application or service. For example, instead of building a language model capable of understanding thousands of different questions, we send the question to an existing AI model and receive its response. You can explore available models and API access through: platform.openai.com You may need to create an account and configure API billing. Important: API usage may cost money. Check the current pricing and your account's available access before making requests. Also, an API key is a private credential. Never publish it in your code, GitHub repository or screenshots. 3. Prepare Termux for Development Open Termux. You should see a terminal where you can enter commands. Don't worry if this looks unfamiliar. We'll explain what each command does. First, update the installed package information. Enter: pkg update && pkg upgrade -y This checks for available package updates and installs them. Next, install Python: pkg install python -y Python is the programming language we'll use to build the assistant. Check whether the installation was successful: python --version You should see a Python version displayed. Now install Git: pkg install git -y Git is a version-control tool that helps developers manage changes to their projects. We won't need Git for the basic assistant, but it's useful to have when developing larger applications. Next, upgrade pip: python -m pip install --upgrade pip Pip is Python's package installer. It allows us to install additional libraries. Our development environment is now ready. 4. Create Your AI Assistant Project Let's create a dedicated folder for the project. Enter: mkdir smart-ai This creates a directory called "smart-ai". Move into it: cd smart-ai Your terminal is now working inside the project directory. Let's create a Python virtual environment. python -m venv venv A virtual environment gives your project its own Python package installation space. Activate it: source venv/bin/activate If activation succeeds, you should see something similar to "(venv)" at the beginning of your terminal prompt. This helps keep project dependencies separate from other Python projects. Now install the official OpenAI Python library: python -m pip install openai Wait for the installation to finish. The library allows our Python application to communicate with the OpenAI API without manually constructing every HTTP request. We are now ready to write the actual assistant. 5. Create Your AI API Key Before writing the code, we need to configure access to the AI model. Visit: platform.openai.com Sign in and navigate to the API key section. Create a new secret API key. Copy it somewhere temporarily safe. Do not share it with anyone. Return to Termux. Enter: export OPENAI_API_KEY="YOUR_API_KEY_HERE" Replace "YOUR_API_KEY_HERE" with your actual API key. For example, the command should follow this structure: export OPENAI_API_KEY="sk-your-private-key" The example above is illustrative, not a working key. This command creates an environment variable that Python can access. Why not simply put the API key inside the Python script? Because separating credentials from application code reduces the chance of accidentally exposing them when sharing your project. Remember that environment variables set this way generally apply to the current shell session. You'll need to configure the key again when starting a new session unless you set up a secure alternative. Never upload your real key to GitHub. 6. Create the Main AI Assistant Now comes the exciting part. We're going to create the actual application. Create a Python file: nano assistant.py Nano is a terminal text editor. Paste the following complete code into the editor. import os from openai import OpenAI Check API credentials API_KEY = os.getenv("OPENAI_API_KEY") if not API_KEY: print("Error: OPENAI_API_KEY is not configured.") raise SystemExit(1) Initialize AI client client = OpenAI(api_key=API_KEY) Choose a model available to your account MODEL = os.getenv("OPENAI_MODEL", "gpt-6-luna") Assistant personality SYSTEM_PROMPT = """ You are Nova, a smart and helpful personal AI assistant. Your responsibilities: 1. Give accurate and useful answers. 2. Explain complicated topics in simple language. 3. Be friendly, respectful and conversational. 4. Ask for clarification when a question is unclear. 5. Avoid inventing information. 6. Admit when you do not know something. 7. Help users solve problems step by step. 8. Keep simple questions concise. 9. Provide detailed explanations when necessary. You should behave like a thoughtful personal assistant, not a machine that simply generates random text. """ Conversation history conversation = [ { "role": "system", "content": SYSTEM_PROMPT } ] Display welcome screen def welcome(): print("\n" + "=" * 45) print(" NOVA AI ASSISTANT") print("=" * 45) print("Your personal AI assistant") print("Powered by Python and an AI model") print("\nCommands:") print("/reset - Start a new conversation") print("/exit - Close the assistant") print("=" * 45) Generate AI response def generate_response(user_message): conversation.append({ "role": "user", "content": user_message }) try: response = client.responses.create( model=MODEL, input=conversation ) answer = response.output_text conversation.append({ "role": "assistant", "content": answer }) return answer except Exception as error: conversation.pop() print("\nSomething went wrong:") print(error) return None Main application def main(): welcome() while True: try: user_message = input("\nYou: ").strip() if not user_message: continue # Exit command if user_message.lower() == "/exit": print("\nNova: Goodbye! See you again.") break # Reset conversation if user_message.lower() == "/reset": conversation.clear() conversation.append({ "role": "system", "content": SYSTEM_PROMPT }) print("\nNova: Conversation reset!") continue # Generate answer print("\nNova is thinking...") answer = generate_response(user_message) if answer: print("\nNova:", answer) except KeyboardInterrupt: print("\n\nNova: Assistant stopped.") break if name == "main": main() Save your file If you're using Nano: 1. Press CTRL + O. 2. Press Enter to confirm the filename. 3. Press CTRL + X to exit. Your Python application is now saved. What did we just create? Let's understand the important sections. The API connection client = OpenAI(api_key=API_KEY) This initializes the API client. It allows our application to communicate with the AI service. The assistant's personality SYSTEM_PROMPT = """ You are Nova, a smart and helpful personal AI assistant. """ This defines the assistant's behaviour. You can change the instructions to create a different personality. For example, you could build: - A programming tutor. - A personal study assistant. - A business assistant. - A writing assistant. - A research assistant. The underlying AI model remains the same, but the instructions influence how it responds. The conversation memory conversation = [ { "role": "system", "content": SYSTEM_PROMPT } ] This creates the initial conversation history. Every user message and assistant response is added to this list. When we send the conversation to the model, it receives the available context. This is how our assistant can understand follow-up questions. However, this is short-term conversational memory, not permanent personal memory. The conversation currently exists in the running Python process. Closing the application clears it. The AI response response = client.responses.create( model=MODEL, input=conversation ) This is where the actual AI interaction happens. We send the conversation to the Responses API. The model processes the information and generates a response. We then retrieve the generated text: answer = response.output_text Finally, the application displays it in Termux. 7. Run Your AI Assistant for the First Time Now let's test everything. Make sure you're still inside the "smart-ai" directory and your virtual environment is activated. Run: python assistant.py If everything is configured correctly, you should see: ============================================= NOVA AI ASSISTANT ============================================= Your personal AI assistant Powered by Python and an AI model Commands: /reset - Start a new conversation /exit - Close the assistant ============================================= You: Congratulations! You have created your first AI-powered assistant using only your Android phone. Try asking: Hello, who are you? Then: Explain artificial intelligence to me. Now test its conversational memory: My name is Daniel. Follow that with: What is my name? The assistant should use the previous message to answer. You can also test: /reset This clears the current conversation. And: /exit This closes the application. If the model identifier in the example is not available to your API account, check the provider's current model catalogue and set another supported model: export OPENAI_MODEL="YOUR_AVAILABLE_MODEL" Then run the application again. 8. How to Make Your Assistant Smarter At this stage, you have a functioning AI assistant. But what makes it smart? The language model provides the intelligence. Our Python application controls how that intelligence is accessed and presented. There are several ways to improve the assistant. A. Give It a Better Personality You can change the system instructions. For example, replace the original personality with: SYSTEM_PROMPT = """ You are Atlas, an intelligent learning assistant. Your mission is to help people understand technology, science, programming and everyday problems. Always explain difficult concepts using simple examples. When teaching programming: 1. Explain the concept. 2. Show a practical example. 3. Explain the code. 4. Identify common mistakes. 5. Give the learner a small exercise. Never pretend to know something you do not know. Prioritize understanding over simply giving answers. """ Now you have a learning-focused assistant. B. Give It a Different Name Find: print("NOVA AI ASSISTANT") Replace it with: print("ATLAS AI ASSISTANT") You can also change the name inside the system instructions. C. Limit Conversation History Our current application sends the entire conversation history with every request. This is useful for understanding previous messages, but long conversations can become expensive and eventually exceed the model's context limit. A simple improvement is to retain only the most recent messages. For example, after adding an assistant response, you could use: conversation[:] = [ conversation[0] ] + conversation[-20:] This retains the system instructions and the latest 20 conversation messages. For a production application, history management should be more careful so that user and assistant messages remain properly paired. D. Make It Remember Conversations Between Sessions Currently, closing Termux clears the conversation. You can extend the project by saving conversation history to a local JSON file. Python includes a built-in library for this: import json You could save the conversation using: with open("memory.json", "w") as file: json.dump(conversation, file, indent=4) And load it when the application starts: with open("memory.json", "r") as file: conversation = json.load(file) These are basic examples. A complete implementation should handle missing files, invalid JSON, reset behaviour and private data. Also, understand the distinction between conversation history and long-term memory. Conversation history stores what was said. A more advanced memory system identifies useful information, stores it separately and retrieves relevant details when needed. You could eventually give your assistant the ability to remember a user's preferred programming language, ongoing projects or learning goals. However, users should have control over what is stored and the ability to delete it. 9. Troubleshooting Common Problems If something doesn't work, don't immediately assume your phone is incompatible. Here are some common problems. Problem 1: Python command not found You probably haven't installed Python correctly. Run: pkg install python Then check: python --version Problem 2: No module named openai The Python library may not have been installed in your active environment. Activate your virtual environment: source venv/bin/activate Install the library: python -m pip install openai Problem 3: API key not found Check whether your environment variable exists: echo $OPENAI_API_KEY If it is empty, configure your API key again: export OPENAI_API_KEY="YOUR_API_KEY" Problem 4: Authentication error Check that: - Your API key is correct. - Your key has not been revoked. - Your API account has access. - Your account has the necessary billing configuration. Never share your API key when requesting technical assistance. Problem 5: Model not found The model name might not be available to your account. Check the provider's current model documentation and select an accessible model. Problem 6: Connection errors The application needs internet access. Check your connection and try again. Remember that Termux runs on Android, so Android may also restrict background processes or terminate long-running sessions. For this beginner project, keep Termux open while using the assistant. 10. What Can You Build Next? You now have a basic AI assistant. But this is only the beginning. The interesting part of software development is taking a working foundation and gradually introducing more useful features. Here are some ideas. 1. Voice assistant Add speech recognition so that users can speak instead of typing. You could also add text-to-speech so the assistant can read responses aloud. 2. Web interface Instead of communicating through the terminal, create a browser-based interface using Python and a lightweight web framework. You could build a proper chat interface with message bubbles, a conversation sidebar and a responsive design. 3. Document assistant Allow users to provide documents and ask questions about their contents. For example, a student could provide study notes and ask the assistant to explain particular sections. 4. Programming assistant Create a specialized assistant that explains programming errors, reviews code and helps beginners understand unfamiliar concepts. 5. Long-term memory Develop a system that stores useful information between conversations. You could use SQLite or another database to organize saved information. 6. Tool integration Eventually, your assistant could perform useful actions rather than simply answering questions. For example, it could calculate values, organize information or interact with approved external services. This is an important step towards building an AI agent. An AI chatbot responds to messages. An AI agent can also use tools to complete tasks, subject to the permissions and rules you give it. 11. Can You Build an AI That Works Completely Offline? Yes, but it is a different project. The assistant we created uses a remotely hosted model. If your internet connection disappears, it cannot generate new AI responses. A completely offline assistant requires a language model that can run locally on your Android device. Projects such as llama.cpp explore running language models on different hardware platforms. However, local AI has additional requirements. Your device needs sufficient: - Available storage. - RAM. - Processing power. - Compatible software. - Battery capacity. Larger models generally require more resources. A small quantized model may be practical on some devices, while a larger model might be extremely slow or fail to run because of memory limitations. Termux also has Android-specific compatibility considerations. Don't assume that every Linux AI installation tutorial will work on Android without modification. For a beginner, starting with an API-powered assistant is usually easier. Once you understand how the application works, you can experiment with local inference. 12. Final Thoughts: You Don't Need an Expensive Computer to Start Building AI One of the biggest barriers to learning software development is the belief that you need expensive equipment before you can begin. That's not always true. An Android phone can provide a surprisingly useful development environment. With Termux and Python, you can experiment with programming, create small applications and communicate with powerful AI models. Of course, a phone has limitations. A larger screen and more powerful hardware make complex development easier. But the most important thing is getting started. You now understand how to: - Prepare a Python development environment. - Install programming libraries. - Connect an application to an AI API. - Create an assistant personality. - Manage conversational context. - Handle basic errors. - Extend an AI application with additional features. Don't just copy the code and stop there. Change the assistant's name. Experiment with its personality. Add new commands. Try saving conversations. Break something, investigate it and fix it. The best way to become a developer is not simply to follow tutorials. It is to understand what you're building and gradually become confident enough to create your own solutions. If you managed to build Nova, you've already taken your first practical step. Your phone is not just a device for consuming technology. It can also be a tool for creating it. --- A little more inspiration I believe technology becomes most valuable when it helps people solve real problems. That is also an idea behind AfriWidget, a project focused on building practical digital tools for education, productivity and everyday needs. If you're interested in seeing how relatively simple web technologies can become useful products, take a look at "AfriWidget" (afriwidget.com). You don't always need to build the biggest technology to make a meaningful difference. Sometimes, solving one problem properly is a great place to start. --- Further Reading - "Termux official documentation" (termux.dev) - "Termux GitHub repository" (termux/termux-app) - "Python documentation" (docs.python.org) - "OpenAI API documentation" (platform.openai.com) - "OpenAI API pricing" (platform.openai.com) - "llama.cpp GitHub repository" (ggml-org/llama.cpp) Disclaimer: This tutorial demonstrates an API-powered AI assistant for educational purposes. API availability, model identifiers, account requirements and pricing can change. Keep your API credentials private and review your provider's current terms before using the application.
こっちは未マージ termux-app#5238
🚀 TERMUX — TURN YOUR ANDROID PHONE INTO A POWERFUL TERMINAL!💻📱 📥 DOWNLOAD TERMUX FROM THESE SOURCES GitHub Releases: github.com/termux/termux-app/releases F-Droid : f-droid.org #Termux #Android #Linux #Programming #Python #OpenSource #CyberSecurity @Noisbethever t.co
Need a terminal on your Android phone? 📱 Termux gives you a Linux-like environment for Git, SSH and Python. Handy for quick tasks away from your laptop. ⌨️ termux/termux-app #Android #浇朋友 #蓝朋友 #互关 #fo
手机上也想用 Git、SSH 和 Python?📱 Termux 给 Android 带来终端与 Linux 环境。出门也能跑命令、连服务器。⌨️ termux/termux-app #Android #浇朋友 #蓝朋友 #互关 #fo
Cara Install Termux + X11 di Android via Github (2026) Cara install dan setup awal Termux beserta Termux:X11 di Android dari nol. Di video ini gw bahas versi Termux dan Termux:X11 yang paling stabil (bukan versi Play Store). 🔗 Join Telegram Group: t.me 🔗 Link Download: - Termux (GitHub): termux/termux-app - Termux:X11 (GitHub): termux/termux-x11 💻 Command yang dipakai di video: pkg update && pkg upgrade ⏱️ Timestamps: 00:00 Intro 00:08 Kenapa jangan versi Play Store? 00:15 Download Termux 01:20 Download Termux:X11 01:37 Install Termux + Termux:X11 02:12 Update & Upgrade Package Di video selanjutnya, kita bakal langsung install Linux Desktop Environment di atas setup Termux:X11 ini. 💻 Device Lenovo Legion Tab (8.8″ Gen 2) s.shopee.co.id #termux #termuxx11 #linuxandroid #android #tutorialtermux
Sentinel-IR 0.1.2:在 Android Termux 上安装、分析 JavaScript 并验证 AST 检测结果 !Image description 无需电脑、无需 Root、无需 API Key:直接用 Android 手机运行 JavaScript 结构分析与回归测试。 Sentinel-IR 是一个用于 JavaScript 代码结构分析的开源工具。它可以从源代码中提取路由、模块导入、环境变量、文件系统操作、网络相关操作以及潜在风险信号,并将这些信息整理成紧凑的结构化报告。 对于 AI Agent 来说,这意味着不必在每一次分析中都直接传入整个源文件。系统可以先获得一份结构化的事实摘要,再根据任务决定是否需要查看原始代码。 本文将两个实践指南合并为一套完整流程: - 从零开始在 Android Termux 中安装 Sentinel-IR。 - 初始化随 npm 包提供的 WebAssembly 解析器。 - 分析一个可复现的 JavaScript 示例。 - 检查 JSON 报告中的结构化事实。 - 使用 Sentinel-IR 0.1.2 验证动态代码执行、变量作用域和 "child_process" 检测。 - 运行针对特定回归场景的测试。 - 检查发布包,并在需要时运行完整开发测试套件。 - 了解分析器的限制,以及如何安全地分享测试结果。 项目链接 - npm 包:npmjs.com - Sentinel-IR 0.1.2:npmjs.com - GitLab 源代码:gitlab.com - 0.1.1 到 0.1.2 的代码变更:gitlab.com --- 一、开始之前:需要准备什么? 你需要: - 一部能够运行 Termux 的 Android 手机。 - 可以访问软件仓库和 npm registry 的网络连接。 - 一些可用存储空间。 - 大约 20 至 30 分钟,具体时间取决于下载速度和设备环境。 不需要 Root 权限、桌面电脑、OpenAI 账户或 AI API Key。 安装 Termux 建议从官方渠道获取 Termux: - F-Droid:f-droid.org - 官方 GitHub:termux/termux-app 不要随意安装聊天群或不明下载网站提供的 APK。 如果手机上已经安装了 Termux,不要为了本教程直接卸载。来自不同发行渠道的版本可能使用不同的签名密钥。 本文的验证原则 本文区分三种不同的检查: 1. 安装检查:确认安装的是指定版本的 npm 包。 2. 功能检查:确认解析器能处理给定的 JavaScript 示例,并输出预期事实。 3. 回归测试:确认特定语法和作用域场景得到预期分类。 通过其中一种检查,不等于证明整个程序安全,也不等于证明分析器覆盖了所有 JavaScript 语法。 二、打开 Termux 并更新软件包 打开 Termux,等待终端提示符出现。 一次复制一个命令块,执行后等待命令结束,再继续下一步。 不要复制文档中的提示符 "$",只复制代码块里的命令。 第 1 步:更新 Termux 运行: pkg update && pkg upgrade -y 这会更新软件包列表并升级已安装的软件包。 如果遇到仓库或镜像错误,先解决软件源问题,不要直接跳过。 第 2 步:安装 Node.js 和 npm Sentinel-IR 要求 Node.js 20 或更新版本。 pkg install nodejs -y 检查版本: node --version npm --version 进一步检查 Node.js 主版本: node -e "const major = Number(process.versions.node.split('.')[0]); console.log('Node.js:', process.version); if (major < 20) { console.error('Sentinel-IR requires Node.js 20 or newer'); process.exit(1); } console.log('PASS: Node.js version is supported');" 预期结果: PASS: Node.js version is supported 如果 Node.js 版本低于 20,请先更新 Termux 软件包并检查可用版本。 三、创建独立测试目录 为了避免修改其他项目,我们先创建一个专门的测试目录。 mkdir -p "$HOME/sentinel-ir-termux-test" cd "$HOME/sentinel-ir-termux-test" pwd 输出路径通常以以下内容开头: /data/data/com.termux/files/home/ 后续测试文件都放在这个目录中。 以后可以使用以下命令返回: cd "$HOME/sentinel-ir-termux-test" 四、安装指定版本 Sentinel-IR 0.1.2 本教程以 0.1.2 为主要验证版本。 首先创建一个最小 npm 项目: npm init -y 安装指定版本: npm install --save-exact sentinel-ir@0.1.2 检查实际安装的版本: npm ls sentinel-ir 预期依赖树中包含: sentinel-ir@0.1.2 然后检查公共 npm registry: npm view sentinel-ir@0.1.2 version npm view sentinel-ir dist-tags --json 版本查询应返回: 0.1.2 发行标签中应包含: { "latest": "0.1.2" } 这里有一个重要区别:本地 "package.json" 中写着某个版本,并不能证明该版本已经在公共 npm registry 中发布。registry 查询可以独立验证这一点。 如果 npm 无法访问 registry,请先检查网络连接: npm ping 不要把网络超时直接当作分析器故障。 五、检查公开 API 运行以下命令,确认需要的函数已经导出: node - <<'NODE' const sentinel = require('sentinel-ir'); for (const name of ['analyzeAsync', 'compress', 'initializeWasm']) { console.log(${name}: ${typeof sentinel[name]}); if (typeof sentinel[name] !== 'function') { console.error(FAIL: missing function ${name}); process.exitCode = 1; } } if (!process.exitCode) { console.log('PASS: expected Sentinel-IR functions are exported'); } NODE 预期结果应包含: analyzeAsync: function compress: function initializeWasm: function PASS: expected Sentinel-IR functions are exported 如果出现 "Cannot find module",请检查当前目录和安装状态: cd "$HOME/sentinel-ir-termux-test" npm ls sentinel-ir 如果安装的不是 0.1.2,请返回安装步骤。 六、初始化 WebAssembly 解析器 Sentinel-IR 包含 WebAssembly 解析路径。在 Android 等环境中,如果可选的原生 Tree-sitter 依赖无法正常构建,可以尝试使用该路径。 运行: node - <<'NODE' const { initializeWasm } = require('sentinel-ir'); initializeWasm() .then(() => { console.log('PASS: Sentinel-IR WebAssembly parser initialized'); }) .catch((error) => { console.error('FAIL: WebAssembly initialization failed'); console.error(error); process.exitCode = 1; }); NODE 预期结果: PASS: Sentinel-IR WebAssembly parser initialized 如果初始化失败,先不要继续假设解析器已经可以工作。 检查安装版本及相关依赖: npm ls sentinel-ir web-tree-sitter ls -lh node_modules/sentinel-ir/wasm/ 检查包中是否包含 JavaScript 对应的 WebAssembly 语法文件: tree-sitter-javascript.wasm 文件缺失、安装不完整或依赖初始化失败,都需要单独调查。 七、创建一个可复现的 JavaScript 示例 接下来创建一个简单的 Express 风格服务器代码。 注意:这里仅分析源代码,不会运行服务器,也不需要安装 Express。 创建文件: cat > sample.js <<'JS' const express = require("express"); const fs = require("fs"); const app = express(); app.post("/upload", (req, res) => { fs.writeFileSync("/tmp/upload", req.body); res.end(); }); app.listen(process.env.PORT); JS 检查文件内容: cat sample.js 检查语法: node --check sample.js 如果语法正确,Node.js 通常不会输出任何内容,并会返回终端提示符。 这个示例刻意包含几个容易识别的结构: - "POST /upload" 路由。 - "express" 和 "fs" 模块导入。 - "process.env.PORT" 环境变量。 - 文件系统写入操作。 这些结构可以用来检查分析器是否提取了预期事实。 八、创建分析脚本 下面的脚本读取指定 JavaScript 文件,将源代码传给 "analyzeAsync()",再通过 "compress()" 生成紧凑报告。 它不会执行输入文件,也不会调用 LLM 或上传源代码。 创建脚本: cat > analyze.js <<'JS' const fs = require('node:fs/promises'); const path = require('node:path'); const { analyzeAsync, compress } = require('sentinel-ir'); async function main() { const inputPath = process.argv[2]; if (!inputPath) { console.error('Usage: node analyze.js <file.js>'); process.exitCode = 1; return; } const source = await fs.readFile(inputPath, 'utf8'); const ir = await analyzeAsync(source, { target: path.basename(inputPath), }); const report = compress(ir); console.log(JSON.stringify(report, null, 2)); if (report.analysisStatus !== 'complete') { console.error( 'WARNING: analysisStatus is not complete. Do not treat this result as a complete structural analysis.' ); process.exitCode = 2; } } main().catch((error) => { console.error('ERROR: analysis could not finish.'); console.error(error && error.stack ? error.stack : error); process.exitCode = 1; }); JS 检查脚本自身的语法: node --check analyze.js 这一步只验证包装脚本的语法,不验证 Sentinel-IR 的检测准确性。 九、运行分析并保存 JSON 报告 执行: node analyze.js sample.js > report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" 查看报告: cat report.json 退出码含义: - "0":脚本生成了 "analysisStatus" 为 "complete" 的报告。 - "2":生成了报告,但分析状态不完整。 - "1":脚本无法完成分析,例如无法读取文件或初始化解析器失败。 对于本文提供的有效 JavaScript 示例,预期可以检查以下内容: - "analysisStatus" 为 "complete"。 - "facts.ast" 为 "true"。 - "facts.routes" 包含 "POST /upload"。 - "facts.imports" 包含 "express" 和 "fs"。 - "facts.env" 包含 "PORT"。 - 报告中包含与路由和文件写入相关的操作或风险信号。 实际报告中的其他字段及其格式可能随输入和实现而变化。 还可以单独查看主要字段: node - <<'NODE' const r = require('./report.json'); console.log('analysisStatus:', r.analysisStatus); console.log('routes:', r.facts.routes); console.log('imports:', r.facts.imports); console.log('environment variables:', r.facts.env); console.log('operations:', r.facts.operations); console.log('risk signals:', r.facts.riskSignals); NODE 十、自动验证预期结果 仅仅看到一份 JSON 并不意味着分析正确。 我们可以编写一个小检查程序,对示例中的已知结构进行断言。 node - <<'NODE' const report = require('./report.json'); const failures = []; if (report.analysisStatus !== 'complete') { failures.push(analysisStatus expected complete, got ${report.analysisStatus}); } if (report.facts?.ast !== true) { failures.push('facts.ast expected true'); } if (!Array.isArray(report.facts?.routes) || !report.facts.routes.includes('POST /upload')) { failures.push('expected route POST /upload was not found'); } if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('express')) { failures.push('expected import express was not found'); } if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('fs')) { failures.push('expected import fs was not found'); } if (!Array.isArray(report.facts?.env) || !report.facts.env.includes('PORT')) { failures.push('expected environment variable PORT was not found'); } if (failures.length) { console.error('FAIL: sample analysis did not match expectations'); for (const failure of failures) { console.error(- ${failure}); } process.exitCode = 1; } else { console.log('PASS: the sample produced the expected structural facts'); } NODE 预期结果: PASS: the sample produced the expected structural facts 这是一个可复现的 smoke test。它证明的是:在当前安装环境中,给定示例产生了检查程序所要求的结构化事实。 它不是完整的安全审计,不是全面的准确率基准测试,也不证明所有 JavaScript 模式都能被正确识别。 十一、尝试分析自己的 JavaScript 文件 完成已知示例的测试后,可以尝试分析自己拥有或有权检查的 JavaScript 文件。 选项 A:文件已经位于 Termux 中 将文件复制到测试目录,或者直接使用其路径。 node analyze.js ./your-file.js > your-file-report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" 将 "your-file.js" 替换成实际文件名。 请为报告使用不同的文件名,避免覆盖之前的 "report.json"。 选项 B:文件位于 Android Downloads 如果需要访问 Android 的共享存储,可以执行: termux-setup-storage 按照 Android 显示的权限提示进行授权。 列出下载目录: ls "$HOME/storage/downloads" 复制一个 JavaScript 文件: cp "$HOME/storage/downloads/example.js" "$HOME/sentinel-ir-termux-test/your-file.js" cd "$HOME/sentinel-ir-termux-test" node analyze.js your-file.js > your-file-report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" 将 "example.js" 替换成实际文件名。 如果文件名包含空格,请保留命令中的引号。 重要限制 Sentinel-IR 当前面向 JavaScript,包括 CommonJS 和 ESM。 它不声称能够可靠地分析所有 TypeScript、复杂 JSX 或其他编程语言。 此外,分析器一次处理一个 JavaScript 文件,不会自动完成跨文件调用图或数据流分析。 十二、理解 analysisStatus "analysisStatus" 是理解报告时最重要的字段之一。 complete 表示 AST 提取成功,源代码解析没有出现导致分析不完整的语法错误。 但这不代表已经发现所有安全问题,也不代表程序一定安全。 incomplete 表示 AST 提取不可用,或者源代码未能被完整解析。 此时输出可能依赖基于文本的回退启发式规则,结果可能出现误报或漏报。 如果报告不完整,不要声称 Sentinel-IR 已经确认该文件安全。 建议检查: node --check sample.js 确认输入是受支持的 JavaScript,并尝试缩小问题示例。 即使状态为 "complete",仍然存在明确的分析边界: - 这是基于语法结构的分析,不是完整语义分析。 - 一次只分析一个文件。 - 不一定能解析别名、动态计算的属性名或跨模块传递的行为。 - 不证明应用程序安全。 - 不能消除 Prompt Injection。 - 不会运行应用程序,也不会替 AI Agent 决定应该采取什么行动。 像 "world.confidence" 这样的字段,也不应被误解为经过统计校准的正确率概率。 --- 第二部分:Sentinel-IR 0.1.2 的 AST 检测改进 十三、为什么 0.1.2 值得单独测试? 0.1.2 的重点不是重新设计整个 API,而是改善若干具体 JavaScript 语法场景中的结构化事实提取。 本次发布重点包括: 1. 识别更多动态代码执行形式。 2. 更好地区分全局 "eval"、"Function" 与同名局部变量。 3. 识别部分使用字符串字面量的计算属性方法调用。 4. 将静态 "child_process" 导入记录为一种潜在能力。 5. 通过回归测试检查正确识别和正确不识别的情况。 在发布验证记录中,开发测试套件通过了 69 项测试,GitLab CI 的三个任务全部成功,独立消费者环境中的定向测试通过了 8 项。 这些结果支持特定实现和测试场景,不代表完整的 JavaScript 安全覆盖。 十四、变量名称相同,不代表行为相同 考虑以下代码: eval(userInput); 以及: parser.eval(userInput); 两者都包含 "eval",但不一定执行相同的操作。 第一种形式通常调用全局 "eval",除非该名称被局部绑定遮蔽。 第二种形式调用 "parser" 对象的方法。它可能只是解析表达式或验证字符串。 如果检测器仅仅搜索字符串 "eval",就容易产生误报。 类似地: function evaluate(value) { return value * 2; } module.exports = { evaluate }; 这里的 "evaluate" 只是一个普通函数名称,并没有执行动态代码。 分析器应该识别实际语法结构,而不是把名称相似当作能力相同。 十五、识别 globalThis 的不同写法 JavaScript 可以通过 "globalThis" 访问全局对象。 以下代码表达了相关的全局操作: eval(userInput); globalThis.eval(userInput); globalThis["eval"](userInput); "Function" 构造器也有类似形式: new Function("return 1"); new globalThis.Function("return 1"); new globalThis["Function"]("return 1"); 这些写法可能对应不同的 AST 节点。 0.1.2 扩展了相应的识别逻辑和测试,覆盖更多显式写出的动态代码执行形式。 它也考虑了 "globalThis" 自身被局部变量遮蔽的情况。如果源文件声明了一个名为 "globalThis" 的局部变量,分析器不能仅凭名称就认定它是真正的全局对象。 十六、区分局部变量与全局 Function 例如: const Function = value => value; Function("ordinary text"); 这里的 "Function" 是局部变量,并不是全局 "Function" 构造器。 类似情况也可能发生在函数参数中: function run(Function) { return Function("ordinary text"); } 或者导入绑定中: import Function from "safe-module"; Function("ordinary text"); 如果检测器把所有名为 "Function" 的调用都标记为动态代码执行,就会把这些情况错误地分类。 0.1.2 在 "src/ast-facts.js" 中扩展了保守的 AST 作用域检查,用于识别局部变量、参数和导入绑定对全局名称的遮蔽。 相关辅助函数包括: - "bindingPatternHasName()" - "lexicalDeclarationHasName()" - "importStatementHasBinding()" - "lexicalScopeHasBinding()" - "varScopeHasBinding()" - "functionScopeHasBinding()" - "isNameShadowed()" - "isUnshadowedGlobalThis()" 这不是完整的 JavaScript 名称解析器,但它比简单搜索关键词更精确。 十七、识别计算属性调用 JavaScript 支持点号调用: cp.execSync("example"); 也支持方括号形式: cp["execSync"]("example"); 对于 AST 来说,这两种写法可能对应不同节点类型。 0.1.2 扩展了 "callTarget()" 对可识别字符串字面量属性的处理,使分析器可以在特定条件下将调用归一化为: object: cp property: execSync 如果 "cp" 已经与 "child_process" 模块关联,这种信息就能帮助分析器识别潜在的进程创建操作。 但以下形式更复杂: cp[methodName]("example"); 如果 "methodName" 的值需要运行时才能确定,分析器不能自动假设它就是 "execSync"。 0.1.2 的改进针对可静态识别的属性,而不是承诺解析所有动态属性。 十八、导入 child_process 不等于执行系统命令 考虑: import { execSync } from "node:child_process"; 这段代码导入了一个能够启动系统命令的 API。 但是,导入本身并不能证明已经执行了命令。 真正的调用可能是: execSync("some-command"); 因此,需要区分两个事实: 1. 文件导入了具有特定能力的模块。 2. 文件中检测到了实际的进程创建调用。 0.1.2 将静态 "child_process" 导入作为能力信号记录,并将它与 "processSpawn" 分开。 例如,仅有导入的测试场景预期包含: childProcess: true processSpawn: false 这里有一个容易误解的地方:当前风险策略仍然可能因为存在 "child_process" 能力而将整体风险设为 "critical"。 这是一种保守的风险分类策略。 "critical" 并不证明文件已经执行了命令,也不证明代码具有恶意。 下游系统应该同时检查能力、实际操作及相关证据,而不是把整体风险标签当作完整的运行时行为描述。 十九、0.1.2 的主要变化 检测领域| 改进内容 动态代码执行| 覆盖更多全局 "eval" 和 "Function" 形式 计算属性| 识别部分字符串字面量方法调用 局部变量| 区分局部 "eval"、"Function" 与全局函数 函数参数| 增加参数遮蔽相关测试 globalThis| 检查全局对象名称被局部变量遮蔽的情况 对象与类方法| 避免把方法名称错误当作词法绑定 ES Module 导入| 为静态 "child_process" 导入添加能力信号 风险证据| 增加针对操作标志、风险等级和风险信号的回归测试 发布验证| 69/69 开发测试、通过的 CI,以及 8/8 定向消费者测试 这些改进的目标是让结构化事实更加准确,而不是让分析器声称自己了解所有程序行为。 --- 第三部分:在 Termux 中复现 0.1.2 的回归测试 二十、创建独立的版本测试目录 前面的基础示例验证了路由、导入和环境变量。 现在,我们测试 0.1.2 特别关注的场景。 mkdir -p "$HOME/sentinel-ir-v012-check" cd "$HOME/sentinel-ir-v012-check" npm init -y npm install --save-exact sentinel-ir@0.1.2 npm ls sentinel-ir 确认安装的是 "sentinel-ir@0.1.2"。 二十一、创建六个定向测试 以下测试会把源代码字符串交给分析器,而不是执行这些源代码。 创建文件: cat > check-v012.js <<'NODE' const assert = require("node:assert/strict"); const { analyzeAsync } = require("sentinel-ir"); const cases = [ { name: "local Function is not the global constructor", source: 'const Function = value => value; Function("ordinary text");', risk: "low", operations: { dynamicEval: false } }, { name: "global Function is dynamic code", source: 'Function("return 1");', risk: "critical", operations: { dynamicEval: true } }, { name: "computed globalThis eval is detected", source: 'globalThis["eval"]("input");', risk: "critical", operations: { dynamicEval: true } }, { name: "computed child_process method is detected", source: 'const cp = require("child_process"); cp["execSync"]("example");', risk: "critical", operations: { childProcess: true, processSpawn: true } }, { name: "ordinary object eval method is not global eval", source: 'const parser = { eval(input) { return input; } }; parser.eval("text");', risk: "low", operations: { dynamicEval: false } }, { name: "static child_process import records capability, not a spawn", source: 'import { execSync } from "node:child_process";', risk: "critical", operations: { childProcess: true, processSpawn: false } } ]; async function main() { for (const item of cases) { const result = await analyzeAsync(item.source, { target: "smoke-test.js" }); assert.equal( result.analysisStatus, "complete", ${item.name}: parsing should complete ); assert.equal( result.world.risk, item.risk, ${item.name}: unexpected risk ); for (const [operation, expected] of Object.entries(item.operations)) { assert.equal( result.facts.operations[operation], expected, ${item.name}: operations.${operation} ); } console.log(PASS: ${item.name} (${result.world.risk})); } console.log(\n${cases.length}/${cases.length} smoke tests passed.); } main().catch(error => { console.error(error); process.exitCode = 1; }); NODE 运行测试: node check-v012.js 如果所有断言都通过,最后一行应为: 6/6 smoke tests passed. 这些测试检查: - 名为 "Function" 的局部变量不会自动被认定为全局构造器。 - 真正的全局 "Function()" 会被识别为动态代码执行。 - "globalThis["eval"]()" 会被识别。 - 与 "child_process" 关联的 "cp["execSync"]()" 会被识别为进程创建操作。 - 普通的 "parser.eval()" 不会仅因名称而被认定为全局 "eval"。 - 静态导入 "child_process" 会记录能力,但不会凭空证明进程已经启动。 最后一项尤其重要:测试预期 "processSpawn" 为 "false",但整体风险仍可能为 "critical"。这是当前风险策略的预期行为,而不是测试矛盾。 如果测试失败,不要直接修改预期值来让它通过。先记录错误、Node.js 版本和安装的包版本。 二十二、检查完整结构化报告 如果你不仅想检查风险等级,还想查看完整的紧凑 IR,可以创建另一个文件: cat > inspect-v012.js <<'NODE' const { analyzeAsync, compress } = require("sentinel-ir"); const code = ` const cp = require("child_process"); cp["execSync"]("example"); `; async function main() { const result = await analyzeAsync(code, { target: "example.js" }); console.log(JSON.stringify(compress(result), null, 2)); } main().catch(error => { console.error(error); process.exitCode = 1; }); NODE 运行: node inspect-v012.js 检查报告中的: - "facts" - "operations" - "riskSignals" - 与识别结果相关的证据 对于这个示例,预期可以看到与 "child_process" 相关的能力,以及被识别的进程创建操作。 具体行号和其他字段可能随输入变化。 重点是:检测结果应当来自解析后的代码结构,而不只是注释或字符串中出现了某个关键词。 二十三、在需要时运行完整开发测试套件 npm 发布包主要包含运行时文件和随包提供的 WebAssembly 语法文件,并不包含完整的开发测试套件。 如果你想检查源代码中的完整测试,需要单独克隆仓库。 cd "$HOME" git clone gitlab.com cd sentinel-ir git checkout adf875a1502e3bcf7242bff85a32dcf62f023c07 npm ci npm test 这里固定了对应 0.1.2 发布的提交,以避免把其他版本的代码误当作本次发布内容。 该发布版本的开发测试结果为: 69 tests passed 0 tests failed 需要注意,Android 上的可选原生 Tree-sitter 依赖可能与桌面 Linux 环境不同。 如果原生解析器无法初始化,前面针对已发布 npm 包的测试使用的是 "analyzeAsync()" 和 WebAssembly 路径。 不要把原生依赖安装失败与所有分析功能都不可用混为一谈,也不要在没有验证的情况下宣称所有 Android 设备都能顺利运行。 二十四、不同验证结果分别证明什么? 本次发布的验证记录包括以下几类检查: 1. 本地开发测试 - 69 项测试通过。 2. GitLab CI - Pipeline:"#2964050242" (gitlab.com) - 对应提交:"adf875a1" - 三个 CI 任务全部成功。 3. 独立消费者测试 发布包 "sentinel-ir-0.1.2.tgz" 被安装到独立消费者目录中。 8 项定向测试通过,涉及变量遮蔽、导入绑定、方法名称、全局动态代码执行及 "globalThis" 访问。 4. 公共 npm registry 通过以下命令检查实际发布状态: npm view sentinel-ir@0.1.2 version npm view sentinel-ir dist-tags --json 这些检查回答的是不同的问题,不能相互替代。 本地测试通过,不代表公共包一定正确发布;CI 通过,也不代表每一种 Android 设备环境都已经被验证。 --- 第四部分:常见问题与故障排查 二十五、Termux 软件仓库错误 如果执行 "pkg update" 时出现仓库不可用或镜像错误,可以运行: termux-change-repo 在界面中选择可用的官方镜像,然后再次运行: pkg update && pkg upgrade -y 请优先使用 Termux 官方文档中的仓库和镜像说明,不要因为某个镜像超时就复制来源不明的安装命令。 二十六、出现 node: command not found 重新检查软件包安装: pkg update pkg install nodejs -y node --version npm --version 如果软件包管理器本身无法正常工作,请先解决仓库问题。 二十七、Node.js 版本低于 20 运行: pkg update && pkg upgrade -y pkg install nodejs -y node --version 如果版本仍然低于 20,请检查当前 Termux 仓库提供的版本。 不要盲目安装多个互相冲突的 Node.js 软件包。 二十八、npm install 出现原生 Tree-sitter 编译错误 Sentinel-IR 的原生 Tree-sitter 依赖是可选的。 如果原生依赖无法构建,可以在专门的测试目录中尝试跳过可选依赖: cd "$HOME/sentinel-ir-termux-test" rm -rf node_modules package-lock.json npm install --save-exact --omit=optional sentinel-ir@0.1.2 这会跳过可选的原生解析器依赖,但不会跳过 WebAssembly 路径所需的常规 "web-tree-sitter" 依赖。 安装后重新检查: npm ls sentinel-ir web-tree-sitter 然后重复 API 检查和 WebAssembly 初始化步骤。 注意:只在本教程创建的专用测试目录中执行清理命令。 不要在需要保留依赖的其他项目中随意删除 "node_modules"。 二十九、Cannot find module 'sentinel-ir' 检查当前目录和依赖: cd "$HOME/sentinel-ir-termux-test" npm ls sentinel-ir 如果没有安装,再运行: npm install --save-exact sentinel-ir@0.1.2 如果仍然失败,请保留完整错误信息。 三十、WebAssembly 初始化失败 检查安装的版本和文件: cd "$HOME/sentinel-ir-termux-test" npm ls sentinel-ir web-tree-sitter ls -lh node_modules/sentinel-ir/wasm/ 确认包中包含 "tree-sitter-javascript.wasm"。 如果文件缺失或安装不完整,可以在专用测试目录中重新安装指定版本。 不要从不明网站下载其他 WebAssembly 二进制文件来替换它。 如果问题仍然存在,请记录 Node.js 版本、包版本和完整错误信息。 三十一、analysisStatus 为 incomplete 首先检查输入文件语法: node --check sample.js 确认输入是受支持的 JavaScript,而不是超出当前支持范围的 TypeScript 或复杂 JSX。 不要将基于回退启发式规则生成的结果当作完整 AST 分析的等价结果。 三十二、预期路由或导入没有被识别 先确认分析的确实是教程中的示例: cat sample.js node analyze.js sample.js > report.json 然后检查: cat report.json 如果示例与教程完全一致、分析状态为 "complete",但预期事实仍然缺失,请保留经过清理的最小示例及报告。 记录包版本、Node.js 版本、实际输出和预期输出。这些信息可以构成一个可复现的问题报告。 不要为了让测试通过而随意修改预期结果。 三十三、npm 无法访问 registry 先检查网络: npm ping npm view sentinel-ir@0.1.2 version 如果 registry 暂时不可用,可以稍后重试,或者切换 Wi-Fi 和移动网络。 在 registry 请求本身无法成功的情况下,不应直接将安装超时归因于分析器代码。 --- 第五部分:安全地分享测试结果 三十四、不要直接公开完整项目报告 Sentinel-IR 的 JSON 报告可能包含: - 导入的模块名称。 - 路由路径。 - 环境变量名称。 - 操作类型。 - 风险信号。 - 目标文件名。 这些信息可能暴露项目的内部结构。 即使报告没有主动提取秘密值,也不能假设报告天然适合公开。 在发布结果之前: 1. 检查报告中的每个字段。 2. 删除或泛化内部路由、文件名、客户信息和专有架构信息。 3. 不要未经许可发布他人的源代码或报告。 4. 优先使用本文提供的合成示例进行演示。 5. 明确说明测试的是合成示例还是自己有权检查的项目。 6. 记录准确的版本、Node.js 版本、命令、预期结果和实际结果。 7. 删除访问令牌、个人文件路径和其他敏感信息。 三十五、可复现测试报告模板 你可以将下面的模板用于 DEV Community、GitLab 讨论区或其他技术社区。 Title: Sentinel-IR 0.1.2 Termux smoke test Device/OS: [Android version and device, if you want to share] Termux source: [F-Droid or official GitHub] Node.js: [output of node --version] Sentinel-IR: 0.1.2 Input: [synthetic sample / my own authorized JavaScript file] Command: node analyze.js sample.js Expected: analysisStatus=complete route POST /upload imports express and fs environment variable PORT Actual: [what really happened] Result: [PASS / FAIL / INCOMPLETE] Notes: [reproducible error or unexpected field, without secrets] 使用你自己的 DEV Community 或 GitLab 账户发布测试结果即可,不需要访问维护者账户。 一份有价值的问题报告应包含最小可公开示例、准确版本、预期行为、实际行为,以及分析状态是否完整。 --- 最终检查清单 在结束之前,请确认以下事项。 - [ ] "node --version" 显示 Node.js 20 或更新版本。 - [ ] "npm ls sentinel-ir" 显示 "sentinel-ir@0.1.2"。 - [ ] "analyzeAsync"、"compress" 和 "initializeWasm" 已正确导出。 - [ ] WebAssembly 初始化成功。 - [ ] 示例文件通过语法检查。 - [ ] "node analyze.js sample.js" 成功生成报告。 - [ ] 报告的 "analysisStatus" 为 "complete"。 - [ ] 路由、导入和环境变量检查通过。 - [ ] 六项 0.1.2 定向 smoke tests 全部通过。 - [ ] 了解 "critical" 风险等级不等于已证明恶意或已执行命令。 - [ ] 了解 smoke test 不是完整安全认证。 如果某一步失败,不要隐藏失败结果。 记录错误、版本和环境信息。一个其他开发者可以复现的失败结果,通常比一句没有细节的“工具无法运行”更有价值。 --- 最后的邀请 Sentinel-IR 的目标不是声称分析器可以理解所有代码,而是在分析开始之前,为下一步决策提供更紧凑、更容易检查的结构化事实。 如果你使用 Android 和 Termux 完成了测试,欢迎分享: - 哪些结构被正确识别? - 哪些事实缺失? - 是否出现误报? - 不同 Node.js 版本或 Android 环境是否产生了不同结果? 请尽量提供可复现的最小示例,而不是只发布截图。 让代码分析的结论可以被检查,让工具的限制也保持可见。 项目地址: - npm:npmjs.com - GitLab:gitlab.com - 0.1.2 变更记录:gitlab.com Sentinel-IR 0.1.2:在 Android Termux 上安装、分析并验证。 !Image description
Warmane on phone quick guide I tried multiple times over the years to play on Warlame servers but I couldn't log in since warden disconnected me every time. Lately a guy on this sub made a post indicating it's plausible. It took me a few minutes to set it up and I was in! It took me a few minutes to set up controls and a day to get used to it, and I was skillcapped again. Auction farming, playing rdf hc, chatting with friends, leveling, etc. It brought me much joy. Even though I don't play wow that much anymore, this was the most fun I had in a while. Right now I'll paste the vibecoded answer from opencode on how to set it up. If you're having difficulties I'd suggest you to install termux on the phone and to get opencode, it'll do everything for you, just send it the github link. I'd suggest you to limit the framerate to 60, mine is at 35 even when I play on my desktop machine. I like old school, non shiny warcraft 3 tyoe of graphics. If you have questions, ask in the comments so everyone can make use of it. I don't reply to messages. Here's the guide: Title: Play WoW 3.3.5a (Warmane) on Android — step-by-step, with background play Body: A lot of people can get WoW running on Android but then it closes the moment they switch apps. I'm sharing an unofficial BannerHub build that keeps WoW running and connected in the background, plus the full setup. Part 1 — Download and install the app 1. Open the repo: codxbre/wow-mobile-bannerhub 2. Go to Releases → v1.0 → download BannerHub-v3.8.1-Normal-BG2.apk. 3. Install it. If you already have BannerHub v3.8.1 Normal, it updates straight over it. If you have a different BannerHub/GameHub variant, uninstall that first. 4. Open the app and allow notifications. When a game is running you'll see a "Game running" notification — that's the background service keeping your session alive. Part 2 — Get WoW from your PC (don't download it on the phone) Downloading the client directly on the phone usually gives you a bare game with no addons or settings. Copy your existing folder instead: 1. On your PC, find your WoW 3.3.5a folder (the one with Wow.exe, Data, Interface, WTF). 2. Copy the whole folder to your phone at: /storage/emulated/0/Download/World of Warcraft 3.3.5a/ 3. Keep Interface/AddOns and WTF — those are your addons and settings. 4. Don't rename Wow.exe. Part 3 — Add the game 1. Open BannerHub and add/import the game. 2. Pick Wow.exe in that folder. 3. Launch. Part 3b — Controls, keybinds & trackpad Quick walkthrough of the in-game Controls tab — on-screen buttons, keybinds, mouse/trackpad gestures, and the virtual controller: youtube.com BannerHub uses the same Controls layout as Winlator/GameHub, so everything in the video applies. Part 4 — If the game won't start 1. Open the game's PC Game Settings. 2. Set GPU Driver → System Driver. 3. Launch again. 4. Still stuck? Open BannerHub's component/firmware section, update the firmware/container, and retry. Part 5 — If you hear sound but the screen is black 1. Close the game. 2. Open World of Warcraft 3.3.5a/WTF/Config.wtf in a text editor. 3. Make sure these lines are there (add them if missing): SET gxWindow "1" SET gxMaximize "1" SET gxResolution "1280x720" 4. Save and launch again. Windowed mode at the container's real resolution fixes the black screen. Part 6 — Playing in the background - Leave the "Game running" notification alone while you play. - On Xiaomi/HyperOS also set Settings → Apps → BannerHub → Battery → No restrictions, and allow background data. - Now you can switch apps or open BannerHub's settings and WoW stays connected. Part 7 — If nothing works: let an AI agent fix it If you've tried everything and the game still fails, you can install a terminal and an AI coding agent on the phone and let it diagnose the setup. 1. Install Termux from F-Droid (f-droid.org) or the GitHub releases (github.com/termux/termux-app/releases). Don't use the Play Store version — it's outdated. 2. Open Termux and run: pkg update -y && pkg upgrade -y pkg install -y curl git termux-setup-storage curl -fsSL opencode.ai | bash opencode 3. In opencode, run /connect and choose a provider with a free tier — for example Google (free API key from Google AI Studio) or OpenRouter (free models). Paste the key, then run /models and pick a model marked free. 4. Paste this prompt (fill in the brackets): I'm on Android (Termux) trying to run World of Warcraft 3.3.5a (Warmane) through BannerHub v3.8.1 Normal (modified APK from codxbre/wow-mobile-bannerhub). My device: [phone model, Android version, GPU]. Problem: [game won't start / black screen with sound / disconnects in background / other]. What I already tried: [GPU Driver = System Driver, config.wtf windowed 1280x720, installed the background APK, battery = No restrictions]. Please: 1. Find and read my logs (logcat, wine.log, f7f8-debug.log) under /storage/emulated/0 and /data/data/com.termux/files/home. 2. Diagnose the actual cause. 3. Fix it step by step. If the APK needs patching, build a new one in the cloud (e.g. GitHub Actions) and put it in /storage/emulated/0/Download. 4. If you need more information, ask me. 5. Follow its steps and try the game again. Notes - This is an unofficial community build. No game files are included — use your own WoW 3.3.5a client. - All credit to The412Banner (BannerHub) and the GameHub team. - Tested with Warmane Icecrown 3.3.5a on a Redmi/Adreno device.
Sentinel-IR on Android: Install It in Termux Mobile and Verify the Output, Step by Step !Image description From a fresh Termux terminal to a real, inspectable JavaScript analysis report. No desktop computer, no API key, no AI account required. > What this guide does: installs the published sentinel-ir@0.1.1 package, initializes its bundled WebAssembly parser, analyzes a tiny JavaScript example, checks expected results, and saves a JSON report. It then shows how to analyze one JavaScript file you own and how to share sanitized findings under your own account. > > What it does not do: it does not prove that a program is secure, scan an entire repository, analyze TypeScript/JSX reliably, or send source code to an LLM. The 0.1.1 release was tested in Termux. This walkthrough uses the published package's documented API and includes troubleshooting because Android and Termux installations can differ. Thanks for support.. Release: "Sentinel-IR-MCP v0.2.2 on GitLab" (gitlab.com) Package: "sentinel-ir-mcp@0.2.2 on npm" (npmjs.com) ⚡ The 20-Second Version You can run a small JavaScript structural analyzer from an Android phone. Termux gives Android a Linux-style terminal, Node.js runs JavaScript, and Sentinel-IR turns a source string into a compact JSON report with facts such as recognized routes, imports, environment variables, operations, and risk signals. The point of this tutorial is simple: do not take my word for it. Install the exact published version, run the sample, and inspect the output yourself. If you find a problem, report it from your account, with enough detail for someone else to reproduce it. Yes, this is the kind of project you can experiment with from bed instead of spending the entire evening scrolling. Your phone is not a magic workstation, and not every idea becomes a product. But it can be enough to run a real, testable experiment. 🗺️ Quick Navigation Tap any link below to jump directly to that section. At the end of each phase, use Contents to return here or Next to continue without scrolling back to the top. - [The 20-Second Version](#the-20-second-version) - [How to read the visual markers](#how-to-read-the-visual-markers) - [Before We Start: What You Need](#before-we-start-what-you-need) - [Phase 0: Open Termux](#phase-0-open-termux-and-understand-the-terminal) - [Phase 1: Update Termux](#phase-1-update-termux-packages) - [Phase 2: Install Node.js](#phase-2-install-nodejs-and-npm) - [Phase 3: Create a test folder](#phase-3-create-a-clean-test-folder) - [Phase 4: Install Sentinel-IR](#phase-4-install-the-exact-published-release) - [Phase 5: Check the API](#phase-5-check-that-the-public-api-exists) - [Phase 6: Initialize WebAssembly](#phase-6-initialize-the-bundled-webassembly-parser) - [Phase 7: Create the sample](#phase-7-create-a-harmless-javascript-sample) - [Phase 8: Create the analysis script](#phase-8-create-a-small-analysis-program) - [Phase 9: Run the analysis](#phase-9-run-the-analysis-and-save-a-report) - [Phase 10: Verify the findings](#phase-10-verify-the-findings-instead-of-just-looking-at-a-json-blob) - [Phase 11: Try your own file (optional)](#phase-11-try-a-javascript-file-of-your-own-optional) - [Option A: File inside Termux](#option-a-the-file-is-already-inside-termux) - [Option B: File in Android Downloads](#option-b-the-file-is-in-android-downloads) - [Phase 12: Understand the result](#phase-12-understand-analysisstatus) - [Phase 13: Share findings safely](#phase-13-share-a-result-without-leaking-your-code) - [Troubleshooting](#troubleshooting-if-something-goes-wrong) - [Repository errors](#repository-errors-when-running-pkg-update) - [node: command not found](#node-command-not-found) - [Node.js is older than version 20](#nodejs-is-older-than-version-20) - [Native build warnings or errors](#npm-install-shows-native-build-warnings-or-errors) - [Cannot find module 'sentinel-ir'](#cannot-find-module-sentinel-ir) - [WebAssembly initialization failed](#webassembly-initialization-failed) - [analysisStatus is incomplete](#analysisstatus-is-incomplete) - [Expected route or import is missing](#the-expected-route-or-import-is-missing) - [npm cannot reach the registry](#npm-cannot-reach-the-registry) - [What Counts as a Successful Finish?](#what-counts-as-a-successful-finish) - [One Final Invitation](#one-final-invitation) How to read the visual markers - 🟦 DO THIS: copy the command block into Termux and press Enter. - ✅ EXPECTED RESULT: compare your terminal output with this example. - ⚠️ IF THIS FAILS: stop at that step and use the linked troubleshooting section. - 🧪 OPTIONAL: skip it on your first run if you only want to verify the package. Do one step at a time. Continue only when the expected result makes sense. The coloured code syntax and headings are part of DEV.to's normal rendering, not evidence that a test passed. 📦 Before We Start: What You Need - An Android phone supported by Termux. - A working internet connection for the initial package downloads. - A little free storage. Node.js and npm dependencies need room, so do not start with your storage completely full. - Around 10 to 20 minutes if package downloads behave. Slow mirrors or older installations can take longer. - No root access, no API key, no OpenAI account, and no desktop computer. Use the official Termux sources. The maintainers document installation through F-Droid and the official GitHub repository. Avoid random APK files from chat groups or download sites. If you already have Termux installed, do not uninstall it casually: builds from different sources may use different signing keys. Update the installation you already have unless you have a specific reason to switch. Official project references: - Sentinel-IR npm package, version 0.1.1 - Sentinel-IR README for tag v0.1.1 - Sentinel-IR source tag v0.1.1 - Official Termux installation instructions --- 🧭 Phase 0: Open Termux and understand the terminal Open Termux. You should see a terminal prompt and a blinking cursor. Type or paste a command, then press Enter. Commands in this guide should be run inside Termux unless a step explicitly says otherwise. A few phone-specific tips: - Paste one code block at a time. Wait for the prompt to return before pasting the next block. - If you see a long stream of installation text, that is normal. Read the last few lines if a command fails. - Do not paste a line that begins with a prompt character such as $. The $ in documentation usually means “type the command after this symbol”. The blocks below omit it. - If Android closes Termux in the background, reopen it and run the last command again. Do not assume a command completed just because you switched apps. - You do not need to grant access to all shared phone storage for the first test. We will create everything inside Termux's private home directory. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 1](#phase-1-update-termux-packages) 🧭 Phase 1: Update Termux packages Run: 🟦 DO THIS · Run in Termux pkg update && pkg upgrade -y pkg update refreshes the package lists. pkg upgrade -y updates installed packages and automatically accepts the package manager's normal confirmation prompt. > ✅ IF IT WORKS: if the command finishes and returns to the prompt, continue. > > ⚠️ IF THIS FAILS: if it stops with a repository or mirror error, jump to [Troubleshooting: repository errors](#repository-errors-when-running-pkg-update) below. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 2](#phase-2-install-nodejs-and-npm) 🧭 Phase 2: Install Node.js and npm Sentinel-IR requires Node.js 20 or newer. npm normally comes with the Termux Node.js package. 🟦 DO THIS · Run in Termux pkg install nodejs -y Now check both tools: 🟦 DO THIS · Run in Termux node --version npm --version Node should print a version number such as v20.x, v22.x, v24.x, or newer. The exact current version depends on the Termux repository and the day you install it. npm should also print a version number. Use this extra check to verify the Node major version numerically: 🟦 DO THIS · Run in Termux node -e "const major = Number(process.versions.node.split('.')[0]); console.log('Node.js:', process.version); if (major < 20) { console.error('Sentinel-IR requires Node.js 20 or newer'); process.exit(1); } console.log('PASS: Node.js version is supported');" ✅ EXPECTED RESULT PASS: Node.js version is supported > ⚠️ IF THIS FAILS: if Node is below 20, do not continue and hope for the best. Update Termux packages and check the available Node package again. See [Troubleshooting: old Node.js](#nodejs-is-older-than-version-20). ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 3](#phase-3-create-a-clean-test-folder) 🧭 Phase 3: Create a clean test folder Keep the experiment separate from your photos, downloads, and other projects. 🟦 DO THIS · Run in Termux mkdir -p "$HOME/sentinel-ir-termux-test" cd "$HOME/sentinel-ir-termux-test" pwd The final command should print a path inside Termux's home directory, usually beginning with /data/data/com.termux/files/home/. Every file created in the remaining steps will live in this folder. You can return to it later with: 🟦 DO THIS · Run in Termux cd "$HOME/sentinel-ir-termux-test" ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 4](#phase-4-install-the-exact-published-release) 🧭 Phase 4: Install the exact published release First, create a minimal local npm project: 🟦 DO THIS · Run in Termux npm init -y Install the exact release covered by this guide, rather than whichever version might be published as latest in the future: 🟦 DO THIS · Run in Termux npm install --save-exact sentinel-ir@0.1.1 This package has a regular web-tree-sitter dependency and optional native Tree-sitter dependencies. The normal install may try to install those optional native packages too. Our test will explicitly use the bundled WebAssembly parser through analyzeAsync(), which is the intended path when native parser packages are unavailable. Check that npm installed the exact version: 🟦 DO THIS · Run in Termux npm ls sentinel-ir You should see sentinel-ir@0.1.1 in the dependency tree. The package is installed locally in this test folder. You do not need a global npm installation and should not use sudo in Termux. You can independently ask the public registry which version it serves: 🟦 DO THIS · Run in Termux npm view sentinel-ir@0.1.1 version ✅ EXPECTED RESULT 0.1.1 > ⚠️ IF THIS FAILS: if this command says it cannot reach the registry, that is a network or registry access issue, not evidence that the analyzer failed. Check your connection and use the troubleshooting section. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 5](#phase-5-check-that-the-public-api-exists) 🧭 Phase 5: Check that the public API exists Run this block exactly as shown: 🟦 DO THIS · Run in Termux node - <<'NODE' const sentinel = require('sentinel-ir'); for (const name of ['analyzeAsync', 'compress', 'initializeWasm']) { console.log(`${name}: ${typeof sentinel[name]}`); if (typeof sentinel[name] !== 'function') { console.error(`FAIL: missing function ${name}`); process.exitCode = 1; } } if (!process.exitCode) { console.log('PASS: expected Sentinel-IR functions are exported'); } NODE The three lines should end in function, followed by: ✅ EXPECTED RESULT PASS: expected Sentinel-IR functions are exported > ⚠️ IF THIS FAILS: if you see Cannot find module, check that your terminal is still in the test directory and run npm ls sentinel-ir again. If the installed version is not 0.1.1, return to Phase 4. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 6](#phase-6-initialize-the-bundled-webassembly-parser) 🧭 Phase 6: Initialize the bundled WebAssembly parser This is a direct check of the WebAssembly initialization path, before we analyze a file. 🟦 DO THIS · Run in Termux node - <<'NODE' const { initializeWasm } = require('sentinel-ir'); initializeWasm() .then(() => { console.log('PASS: Sentinel-IR WebAssembly parser initialized'); }) .catch((error) => { console.error('FAIL: WebAssembly initialization failed'); console.error(error); process.exitCode = 1; }); NODE ✅ EXPECTED RESULT PASS: Sentinel-IR WebAssembly parser initialized > ⚠️ IF THIS FAILS: if initialization fails, do not quietly move to the next step. See [Troubleshooting: WebAssembly initialization](#webassembly-initialization-failed). The usual checks are whether the package finished installing, whether the packaged WASM file exists, and whether the exact version is installed. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 7](#phase-7-create-a-harmless-javascript-sample) 🧭 Phase 7: Create a harmless JavaScript sample We will analyze text that looks like a tiny Express-style server. Sentinel-IR analyzes the source text; this guide does not run the server. You do not need to install Express because the code is only the input to the parser. Create the sample: 🟦 DO THIS · Run in Termux cat > sample.js <<'JS' const express = require("express"); const fs = require("fs"); const app = express(); app.post("/upload", (req, res) => { fs.writeFileSync("/tmp/upload", req.body); res.end(); }); app.listen(process.env.PORT); JS Check the file was created: 🟦 DO THIS · Run in Termux cat sample.js You should see the JavaScript block you just pasted. You can also check its syntax with Node.js without executing the server: 🟦 DO THIS · Run in Termux node --check sample.js If the syntax check succeeds, Node normally prints nothing and returns to the prompt. If it reports a syntax error, recreate the file using the full cat block above. Be careful not to include the Markdown code fences in the file. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 8](#phase-8-create-a-small-analysis-program) 🧭 Phase 8: Create a small analysis program Now create a reusable script. It reads one JavaScript file, passes the text to analyzeAsync(), compresses the result, and prints JSON. It does not execute the input file, call an LLM, or upload the input. 🟦 DO THIS · Run in Termux cat > analyze.js <<'JS' const fs = require('node:fs/promises'); const path = require('node:path'); const { analyzeAsync, compress } = require('sentinel-ir'); async function main() { const inputPath = process.argv[2]; if (!inputPath) { console.error('Usage: node analyze.js <file.js>'); process.exitCode = 1; return; } const source = await fs.readFile(inputPath, 'utf8'); const ir = await analyzeAsync(source, { // Use only the filename in the report, not the full private device path. target: path.basename(inputPath), }); const report = compress(ir); console.log(JSON.stringify(report, null, 2)); if (report.analysisStatus !== 'complete') { console.error( 'WARNING: analysisStatus is not complete. Do not treat this result as a complete structural analysis.' ); process.exitCode = 2; } } main().catch((error) => { console.error('ERROR: analysis could not finish.'); console.error(error && error.stack ? error.stack : error); process.exitCode = 1; }); JS Check the wrapper's own syntax: 🟦 DO THIS · Run in Termux node --check analyze.js Again, a successful syntax check normally prints nothing. This tests the small wrapper, not Sentinel-IR's accuracy. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 9](#phase-9-run-the-analysis-and-save-a-report) 🧭 Phase 9: Run the analysis and save a report Run: 🟦 DO THIS · Run in Termux node analyze.js sample.js > report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" The JSON is saved in report.json, not lost in a wall of terminal output. The exit code means: - 0: the script produced a result whose analysisStatus is complete. - 2: a result was produced, but the analysis status was not complete. Read the warning and do not count this as a successful complete analysis. - 1: the wrapper could not finish, for example because it could not read the input or initialize the parser. Display the report: 🟦 DO THIS · Run in Termux cat report.json The report is JSON. Its exact formatting and some values can vary with the input, but for the supplied valid JavaScript sample you should expect structural facts resembling these: - analysisStatus should be complete. - facts.ast should be true. - facts.routes should include POST /upload. - facts.imports should include express and fs. - facts.env should include PORT. - The report should include recognized operations and risk signals related to the route and file write. The report's risk estimate is not a verdict that this example is safe or unsafe. The sample deliberately includes an HTTP route and a filesystem write so there is something tangible to inspect. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 10](#phase-10-verify-the-findings-instead-of-just-looking-at-a-json-blob) 🧭 Phase 10: Verify the findings instead of just looking at a JSON blob Run an automatic check against the results we expect from the sample: 🟦 DO THIS · Run in Termux node - <<'NODE' const report = require('./report.json'); const failures = []; if (report.analysisStatus !== 'complete') { failures.push(`analysisStatus expected complete, got ${report.analysisStatus}`); } if (report.facts?.ast !== true) { failures.push('facts.ast expected true'); } if (!Array.isArray(report.facts?.routes) || !report.facts.routes.includes('POST /upload')) { failures.push('expected route POST /upload was not found'); } if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('express')) { failures.push('expected import express was not found'); } if (!Array.isArray(report.facts?.imports) || !report.facts.imports.includes('fs')) { failures.push('expected import fs was not found'); } if (!Array.isArray(report.facts?.env) || !report.facts.env.includes('PORT')) { failures.push('expected environment variable PORT was not found'); } if (failures.length) { console.error('FAIL: sample analysis did not match expectations'); for (const failure of failures) console.error(`- ${failure}`); process.exitCode = 1; } else { console.log('PASS: the sample produced the expected structural facts'); } NODE ✅ EXPECTED RESULT PASS: the sample produced the expected structural facts This is a reproducible smoke test. It shows that this installed package can parse this particular sample and return the facts checked by the script. It is not a broad benchmark, a full test suite, or proof that every JavaScript pattern is recognized correctly. You can also print the most useful fields without dumping the whole report: 🟦 DO THIS · Run in Termux node - <<'NODE' const r = require('./report.json'); console.log('analysisStatus:', r.analysisStatus); console.log('routes:', r.facts.routes); console.log('imports:', r.facts.imports); console.log('environment variables:', r.facts.env); console.log('operations:', r.facts.operations); console.log('risk signals:', r.facts.riskSignals); NODE ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 11](#phase-11-try-a-javascript-file-of-your-own-optional) 🧭 Phase 11: Try a JavaScript File of Your Own · 🧪 OPTIONAL You have already tested the package with a known sample. Only now try your own input. Only analyze code you own or are authorized to inspect. Start with one .js file, not an entire repository. Sentinel-IR analyzes one JavaScript file at a time; it does not combine calls or data flow across files. 📁 Option A: The file is already inside Termux Copy your file into the test directory, or run the analyzer with its path: 🟦 DO THIS · Run in Termux node analyze.js ./your-file.js > your-file-report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" Replace your-file.js with the real filename. If you need to keep a report, give it a different name so you do not overwrite report.json. 📱 Option B: The file is in Android Downloads For this optional path, grant Termux shared-storage access only if you need it: 🟦 DO THIS · Run in Termux termux-setup-storage Android may show a permission dialog. Approve it if you want Termux to read your shared files. Then list Downloads: 🟦 DO THIS · Run in Termux ls "$HOME/storage/downloads" Copy one JavaScript file into the private test folder, replacing example.js with its exact filename: 🟦 DO THIS · Run in Termux cp "$HOME/storage/downloads/example.js" "$HOME/sentinel-ir-termux-test/your-file.js" cd "$HOME/sentinel-ir-termux-test" node analyze.js your-file.js > your-file-report.json rc=$? printf 'Analyzer exit code: %s\n' "$rc" 💡 TIP: if the filename contains spaces, keep the quotation marks. If the file is not listed in Downloads, check the correct folder name with ls. You do not need to enable this permission for the earlier sample test. A file can be JavaScript-shaped but still use syntax that Sentinel-IR does not support. The package currently targets JavaScript, including CommonJS and ESM. It does not claim general TypeScript, JSX-heavy, or other-language support. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 12](#phase-12-understand-analysisstatus) 🧭 Phase 12: Understand analysisStatus This field is one of the most important parts of the output. - complete means AST extraction succeeded and the source parsed without syntax errors. It does not mean every security issue was found. - incomplete means AST extraction was unavailable or the source did not parse cleanly. The output may rely on text-based fallback heuristics, which can be wrong in either direction. > ⚠️ IF THIS FAILS: if a report is incomplete, do not write “Sentinel-IR cleared this file” or “the code is safe”. Instead, report that the result was incomplete and explain which input you used. Depending on the file, check the syntax, make sure it is plain supported JavaScript, and try a smaller reproducible example. Even complete has strict limits: 1. It is a syntax-based structural report, not full semantic analysis. 2. It examines one file at a time. 3. It may not resolve aliases, computed properties, or behavior passed between modules. 4. It does not prove the application is secure. 5. It reduces some untrusted text passed onward, but it does not eliminate prompt injection. 6. It does not run your app or decide what an AI agent should do. Do not treat values such as world.confidence as calibrated probabilities. They are configuration or metadata fields, not a validated guarantee that the output is correct. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Phase 13](#phase-13-share-a-result-without-leaking-your-code) 🧭 Phase 13: Share a result without leaking your code Now for the part that matters if you want to publish a finding. The JSON report may contain names of imported packages, route paths, environment-variable names, operation names, risk signals, and the target filename you supplied. Those can reveal internal architecture. Even if a secret value is not intentionally extracted, never assume any generated report is automatically safe to publish. Before posting: 1. Open the report and review every field. 2. Remove or generalize private route names, internal package names, filenames, customer information, and anything that reveals a secret or proprietary design. 3. Do not publish private source code or a report from somebody else's code without permission. 4. Prefer the small synthetic sample from this guide when demonstrating basic behavior. 5. State clearly whether you tested the synthetic sample or your own project. 6. Include the exact version, Node version, command, expected result, actual result, and error text if something failed. Remove access tokens and personal filesystem paths. 7. Do not claim that a single smoke test proves the analyzer is secure or accurate in all cases. You can check the environment before writing your report: 🟦 DO THIS · Run in Termux node --version npm --version npm ls sentinel-ir Here is a report template you can adapt for DEV Community, GitLab, a discussion thread, or your own blog: 📝 COPY THIS TEMPLATE AND FILL IT IN Title: Sentinel-IR 0.1.1 Termux smoke test Device/OS: [Android version and device, if you want to share] Termux source: [F-Droid or official GitHub] Node.js: [output of node --version] Sentinel-IR: 0.1.1 Input: [synthetic sample / my own authorized JavaScript file] Command: node analyze.js sample.js Expected: analysisStatus=complete, route POST /upload, imports express and fs, env PORT Actual: [what really happened] Result: [PASS / FAIL / INCOMPLETE] Notes: [reproducible error or unexpected field, without secrets] Use your own DEV Community or GitLab account to publish your own test result. You do not need access to the maintainer's account. A useful bug report includes a minimal input that you are allowed to share, the exact version, what you expected, what happened, and whether analysisStatus was complete. ⬆️ [Contents](#quick-navigation) · ➡️ [Next: Troubleshooting](#troubleshooting-if-something-goes-wrong) 🧰 Troubleshooting: If Something Goes Wrong Repository errors when running pkg update > ⚠️ IF THIS FAILS: if Termux reports that a repository is unreachable or under maintenance, check your connection and change the Termux mirror: 🟦 DO THIS · Run in Termux termux-change-repo Choose an available official mirror in the interface, then run: 🟦 DO THIS · Run in Termux pkg update && pkg upgrade -y The Termux maintainers document repository and mirror fixes in their Package Management guide. Do not paste commands from unrelated download sites just because a mirror timed out. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) node: command not found Install Node.js again from Termux: 🟦 DO THIS · Run in Termux pkg update pkg install nodejs -y node --version npm --version > ⚠️ IF THIS FAILS: if the package manager itself is broken, resolve the repository issue first. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) Node.js is older than version 20 Run: 🟦 DO THIS · Run in Termux pkg update && pkg upgrade -y pkg install nodejs -y node --version > ⚠️ IF THIS FAILS: if the installed version is still below 20, do not continue with this release. Check the available packages in your Termux repository and follow the official Termux package guidance. Do not install two alternative Node packages blindly; they can conflict. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) npm install shows native build warnings or errors Sentinel-IR's native Tree-sitter packages are optional. This guide uses the bundled WASM parser, so retry the installation without optional dependencies: 🟦 DO THIS · Run in Termux cd "$HOME/sentinel-ir-termux-test" rm -rf node_modules package-lock.json npm install --save-exact --omit=optional sentinel-ir@0.1.1 This deliberately skips optional native parser packages. It does not skip the regular web-tree-sitter dependency needed by the WASM path. Then repeat Phase 5 and Phase 6. Only run the cleanup command in the dedicated test folder created by this guide. Do not run rm -rf node_modules in a project where you need to preserve the current installation. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) Cannot find module 'sentinel-ir' Check your location and installation: 🟦 DO THIS · Run in Termux cd "$HOME/sentinel-ir-termux-test" npm ls sentinel-ir > ⚠️ IF THIS FAILS: if it is missing, install the pinned release again: 🟦 DO THIS · Run in Termux npm install --save-exact sentinel-ir@0.1.1 ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) WebAssembly initialization failed First verify the package and WASM file are present: 🟦 DO THIS · Run in Termux cd "$HOME/sentinel-ir-termux-test" npm ls sentinel-ir web-tree-sitter ls -lh node_modules/sentinel-ir/wasm/ The published package should include tree-sitter-javascript.wasm. If the folder or file is missing, retry the install in the test directory. Check that the install finished and that the package version is 0.1.1. > ⚠️ IF THIS FAILS: if it still fails, keep the complete error message and your Node version. Do not replace the WASM file with an unrelated binary from a random website. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) analysisStatus is incomplete The package may have been unable to perform AST extraction, or the file did not parse cleanly. Check: 🟦 DO THIS · Run in Termux node --check sample.js Remember that the basic test expects JavaScript. TypeScript, JSX-heavy syntax, or other programming languages are outside the documented support claim. Do not treat fallback results as an equivalent structural parse. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) The expected route or import is missing First confirm that you are analyzing the sample from this guide, not another file: 🟦 DO THIS · Run in Termux cat sample.js node analyze.js sample.js > report.json Then inspect report.json. If the sample is exactly as shown, analysisStatus is complete, and the expected fact is still absent, preserve a sanitized copy of the sample and report the mismatch with package version and Node version. That is a useful reproducible issue. Do not change the expected output just to force a pass. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) npm cannot reach the registry Check connectivity, then retry: 🟦 DO THIS · Run in Termux npm ping npm view sentinel-ir@0.1.1 version > ⚠️ IF THIS FAILS: if the registry is temporarily unavailable on your connection, retry later or switch between Wi-Fi and mobile data. Do not post an installation timeout as an analyzer defect until the registry request itself works. ⬆️ [Troubleshooting index](#troubleshooting-if-something-goes-wrong) ✅ What Counts as a Successful Finish? By the end, all of these should be true: - node --version is at least 20. - npm ls sentinel-ir shows version 0.1.1. - The expected exported functions are present. - initializeWasm() finishes successfully. - node analyze.js sample.js writes report.json. - The report says analysisStatus: "complete" for the sample. - The verification script prints PASS: the sample produced the expected structural facts. - You understand that this is a smoke test, not a security certification. ✅ IF ALL CHECKS PASS: you have reproduced a small test of the published package on your phone. That is already useful: you did not need to trust a screenshot or a claim, because you ran the commands and inspected the output yourself. > ⚠️ IF THIS FAILS: if a check fails, that is not a personal failure. Keep the error, report the environment, and share only sanitized reproducible details. A failed reproducible test is more useful than a vague statement that something “doesn't work”. ⬆️ [Contents](#quick-navigation) · ➡️ [Final invitation](#one-final-invitation) 🚀 One Final Invitation Try it with the sample first. Then, if you have a JavaScript file you own and are comfortable inspecting, try that one. Check whether the facts match what the code actually contains. Look for missing facts and false positives. Tell me what you found, including the parts that did not work. This is a small structural analyzer, not an oracle. The interesting part begins when more people can run the same experiment, compare observations, and challenge the claims with evidence. Built and released from a phone-friendly workflow. Verified by your own terminal.