merakcode 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +361 -2
- package/THIRD_PARTY_NOTICES.md +67 -0
- package/bin/cli-name.cjs +24 -0
- package/bin/crash-evidence.cjs +98 -0
- package/bin/merak +100 -0
- package/package.json +27 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tong Tong
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,362 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="apps/desktop/renderer/public/logo.svg" width="72" alt="MerakCode" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">MerakCode</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">Aiming to be the best AI coding tool to work with</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://github.com/TongTong313/merakcode/actions/workflows/ci.yml"><img src="https://github.com/TongTong313/merakcode/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
|
|
11
|
+
<a href="https://github.com/TongTong313/merakcode/releases"><img src="https://img.shields.io/github/v/release/TongTong313/merakcode?include_prereleases" alt="Release" /></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/merakcode"><img src="https://img.shields.io/npm/v/merakcode" alt="npm" /></a>
|
|
13
|
+
<a href="https://nodejs.org/"><img src="https://img.shields.io/badge/node-%3E%3D26.12-339933?logo=nodedotjs&logoColor=white" alt="Node.js" /></a>
|
|
14
|
+
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-7.0-3178C6?logo=typescript&logoColor=white" alt="TypeScript" /></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center"><a href="README.md">简体中文</a> · English</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
MerakCode is an open-source AI coding tool. Beyond strong coding skills, it can help with anything you need AI for. Now that AI writes far faster than people can read, MerakCode puts a lot of care into how people and the agent work together. Collaboration groups let Claude Code, Codex, OpenCode and other products work together, and MerakCode keeps refining how you review what the agent produces, so that its output is what you expect. The aim is to be the best AI coding tool to use, not the most powerful one.
|
|
22
|
+
|
|
23
|
+
We open-sourced this project to make up for a regret we have carried, and in the hope that the community can keep it going. The name comes from Merak, the star in the Big Dipper that, together with Dubhe, points to Polaris. We hope MerakCode does the same and points each of your ideas in the right direction.
|
|
24
|
+
|
|
25
|
+
## What it does
|
|
26
|
+
|
|
27
|
+
- **AI coding**: strong project-level coding across many languages, frameworks, paradigms and styles. Honestly, this part is no different from other AI coding products. You be the judge, and if you like it, a Star is the best way to support us.
|
|
28
|
+
- **Collaboration across products**: MerakCode is designed around people and the agent working together. It has a review interface built specifically for checking what the agent produces (desktop app only) and a complete permission system for what the agent may do. It can also work alongside other AI coding products that ship a CLI, so the collaboration reaches across products.
|
|
29
|
+
- **Model setup**: connect all kinds of model providers (only 8 for now, more to come) as well as local models. MerakCode can also use models through API relay services.
|
|
30
|
+
- **Secure and reliable**: commands the agent runs go into our own OS sandbox. They cannot read key folders such as `~/.ssh` or `~/.aws`, can write only the workspace, temp folders and package manager caches, and need your approval for hosts that are not on the allowlist. This is a small product built by a few people, with no server side (no time to build one...). We don't collect, and couldn't collect, any usage data, so there is nothing of yours to leak.
|
|
31
|
+
- **Extensible**: MCP, skills, plugins, custom agents and slash commands.
|
|
32
|
+
- **Beyond coding**: AI coding is one of the hardest kinds of task there is, so using MerakCode for other things works just fine.
|
|
33
|
+
- **Build your own**: MerakCode ships an agent SDK, and every MerakCode product is built on it. You can build your own AI coding tool on the same engine.
|
|
34
|
+
|
|
35
|
+
## How to install
|
|
36
|
+
|
|
37
|
+
### Desktop app
|
|
38
|
+
|
|
39
|
+
Download from the [Releases](https://github.com/TongTong313/merakcode/releases) page:
|
|
40
|
+
|
|
41
|
+
| System | File |
|
|
42
|
+
| ------- | --------------------------------------------------------------------------------- |
|
|
43
|
+
| Windows | `MerakCode-<version>-windows-x64.exe` |
|
|
44
|
+
| macOS | `MerakCode-<version>-darwin-arm64.dmg` (Apple silicon), `-darwin-x64.dmg` (Intel) |
|
|
45
|
+
| Linux | `MerakCode-<version>-linux-x64.AppImage` or `.deb` |
|
|
46
|
+
|
|
47
|
+
The desktop app ships with its own engine; you do not need the command-line version as well.
|
|
48
|
+
|
|
49
|
+
The installers are not code-signed yet, so the system stops them the first time:
|
|
50
|
+
|
|
51
|
+
- **Windows**: when you see "Windows protected your PC", click "More info", then "Run anyway".
|
|
52
|
+
- **macOS**: if the app "cannot be opened", go to System Settings → Privacy & Security and click "Open Anyway" near the bottom.
|
|
53
|
+
|
|
54
|
+
Unsigned macOS builds, and Linux installs from a `.deb`, cannot update themselves. When a new version is out, the app sends you to the download page.
|
|
55
|
+
|
|
56
|
+
### Command line
|
|
57
|
+
|
|
58
|
+
The command-line version has no UI. It is for one-off tasks in a terminal, scripts, and editors (through ACP). It shares its config and keys with the desktop app.
|
|
59
|
+
|
|
60
|
+
macOS / Linux:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
curl -fsSL https://github.com/TongTong313/merakcode/releases/latest/download/install.sh | sh
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Windows (PowerShell):
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
irm https://github.com/TongTong313/merakcode/releases/latest/download/install.ps1 | iex
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or with npm (the package brings its own runtime; any Node.js 18 or newer can install it):
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
npm install -g merakcode
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The command is `merak`. Upgrade later with `merak upgrade` (or `merak update`).
|
|
79
|
+
|
|
80
|
+
To check a download yourself, put the release's `SHA256SUMS` in the same folder as the file and run:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
sha256sum -c SHA256SUMS --ignore-missing # Linux
|
|
84
|
+
grep 'darwin-arm64.tar.gz' SHA256SUMS | shasum -a 256 -c # macOS (Apple silicon)
|
|
85
|
+
grep 'darwin-x64.tar.gz' SHA256SUMS | shasum -a 256 -c # macOS (Intel)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The `shasum` that ships with macOS has no `--ignore-missing`, so the commands above check only the line for the file you downloaded.
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
# Windows: the output must equal the value on this file's line in SHA256SUMS
|
|
92
|
+
(Get-FileHash .\merakcode-<version>-windows-x64.zip).Hash.ToLower()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Uninstall
|
|
96
|
+
|
|
97
|
+
On Windows, if you set up the sandbox, first click "Reset" under Settings → Permissions & security in the desktop app (or run `merak sandbox reset`). It removes the sandbox account and firewall rule and takes back the folder permissions it was given.
|
|
98
|
+
|
|
99
|
+
- Desktop app: uninstall it from the system's app list.
|
|
100
|
+
- Installed with the script: on macOS / Linux delete `~/.local/bin/merak`; on Windows remove `~\.merakcode\bin` from your user PATH.
|
|
101
|
+
- Installed with npm: `npm uninstall -g merakcode`.
|
|
102
|
+
- Config, sessions, logs and caches all live in one folder, `~/.merakcode` (on Windows `~` is `C:\Users\<you>`; the `MERAKCODE_HOME` environment variable moves it). Delete it if you no longer need it.
|
|
103
|
+
|
|
104
|
+
## Quick start
|
|
105
|
+
|
|
106
|
+
Open the desktop app and click "Open folder" to pick your project.
|
|
107
|
+
|
|
108
|
+
The first time, connect a model provider: on the onboarding screen, pick a provider and enter its API key (change it later under Settings → Models & providers). The built-in catalog is OpenAI, Anthropic, Google, Alibaba Cloud Model Studio, Zhipu AI, DeepSeek, Moonshot AI and OpenRouter. Any other service is an OpenAI-compatible provider in your config, with its URL, model ids and API key.
|
|
109
|
+
|
|
110
|
+
Then just say what you want:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
Add unit tests for formatDate in utils/date.ts
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Handy actions (`⌘` on macOS, `Ctrl` on Windows and Linux):
|
|
117
|
+
|
|
118
|
+
| Action | What it does |
|
|
119
|
+
| --------------------- | ----------------------------------------------------------------------------- |
|
|
120
|
+
| `⌘/Ctrl+K` | Command palette: search conversation titles, conversation content or commands |
|
|
121
|
+
| `⌘/Ctrl+N` | New conversation |
|
|
122
|
+
| `⌘/Ctrl+G` | New collaboration group |
|
|
123
|
+
| `⌘/Ctrl+,` | Open settings |
|
|
124
|
+
| `⌘/Ctrl+J` | Open or close the terminal |
|
|
125
|
+
| `⌘/Ctrl+B` | Show or hide the side panel |
|
|
126
|
+
| `Shift+Tab` | Switch permission mode |
|
|
127
|
+
| Type `/` in the input | Pick a slash command, such as `/compact` to shrink a long conversation |
|
|
128
|
+
| Type `@` in the input | Reference a file in the project |
|
|
129
|
+
|
|
130
|
+
## Commands
|
|
131
|
+
|
|
132
|
+
The command-line version runs in a terminal. If you have not connected a model provider in the desktop app, run `merak provider login` first. Then run a task in your project folder and get the result printed:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
cd your-project
|
|
136
|
+
merak run "Explain how src/index.ts starts up"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| Command | What it does |
|
|
140
|
+
| ----------------------------- | --------------------------------------------------------------------------------- |
|
|
141
|
+
| `merak run "<task>"` | Run one task and print the result |
|
|
142
|
+
| `merak provider login` | Connect a model provider; `list` shows the connected ones, `logout` removes one |
|
|
143
|
+
| `merak serve --port 4096` | Start only the engine, for the SDK or other programs |
|
|
144
|
+
| `merak upgrade` (or `update`) | Upgrade. `--check` only looks for a new version, `--yes` skips the question |
|
|
145
|
+
| `merak models` | List the models you can use |
|
|
146
|
+
| `merak mcp list` | Show MCP server status |
|
|
147
|
+
| `merak sandbox status` | Is the sandbox on? `setup` turns it on, `reset` removes it |
|
|
148
|
+
| `merak doctor` | Check the install, config, models and sandbox, and say what is wrong |
|
|
149
|
+
| `merak logs` | Where the logs are and recent runs; `--tail` follows the newest log |
|
|
150
|
+
| `merak bug-report` | Zip the checks, config and logs for an issue; keys and conversations are left out |
|
|
151
|
+
| `merak acp` | Run as an [ACP](https://agentclientprotocol.com) agent for editors such as Zed |
|
|
152
|
+
|
|
153
|
+
Add `--help` to any command for the full details.
|
|
154
|
+
|
|
155
|
+
### In your editor (ACP)
|
|
156
|
+
|
|
157
|
+
Editors that speak [ACP](https://agentclientprotocol.com) can use MerakCode as their agent. For Zed, add this to `~/.config/zed/settings.json`:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"agent_servers": {
|
|
162
|
+
"MerakCode": { "command": "merak", "args": ["acp"] }
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Permissions and the sandbox
|
|
168
|
+
|
|
169
|
+
MerakCode edits files and runs commands on your computer, so every action goes through the permission mode first: do it, ask you, or refuse. There is no category called an ordinary file. The rules are:
|
|
170
|
+
|
|
171
|
+
- **Edits inside the workspace.** If no directory or file name on the path relative to the workspace starts with `.`, ask mode and auto mode edit it immediately. If any segment starts with `.` (`.git`, `.github`, `.env`, `src/.hidden/a.ts`), ask mode asks first and auto mode edits it immediately. Read-only mode never edits, and an allow rule in the config cannot override that.
|
|
172
|
+
- **Reads.** A file inside the workspace that is not a secret is read immediately in every mode. A non-secret file outside the workspace asks in read-only and ask mode, and is read immediately in auto mode. Secrets always ask. A secret is a file named `.env`, or `.env.*` other than `.env.example`, `.env.sample`, `.env.template` and `.env.dist`; `id_rsa`, `id_dsa`, `id_ecdsa` or `id_ed25519`, with an optional extra suffix; `credentials` or `credentials.json`; an extension of `.pem`, `.key`, `.p12`, `.pfx`, `.keystore` or `.jks`; or `.npmrc`, `.pypirc`, `.netrc`, `.git-credentials` or `.pgpass`. Files under `.ssh`, `.aws`, `.azure`, `.kube`, `.gnupg`, `.docker`, `.config/gcloud` or `.config/gh` in your home directory count too.
|
|
173
|
+
- **Commands.** Commands that certainly do not change files (`ls`, `git status`, `git diff`, `rg`, and the rest of that fixed list) run in every mode. Anything that might change files counts as a file-changing command. File-changing commands, and `rm`, `rmdir`, `unlink`, `shred`, `git clean`, `git reset --hard` and `find -delete`, are refused in read-only mode, asked about in ask mode, and run immediately in auto mode. Risky commands are refused in read-only mode and asked about in ask and auto mode: `sudo`, `su`, `doas`, `pkexec`, `runas`, `dd` when it does not target a whole disk, `shutdown`, `reboot`, `chown`, and `git push`, `npm publish`, `npm unpublish`, `pnpm publish`, `yarn publish`, `bun publish`, `cargo publish`, `gem push`, `twine upload`, `docker push`, `gh release`, `gh pr`, `helm push`. `rm -rf /` (and the home directory), recursively chmodding those locations to `777`, `mkfs`, `dd` onto a whole disk, `format`, `diskpart` and a fork bomb are refused by default. In ask and auto mode they run only when the config explicitly allows them. In read-only mode an allow rule still does not.
|
|
174
|
+
- **Websites.** The allowlist matches hostnames exactly; a subdomain does not count. These hosts are reached immediately: `registry.npmjs.org`, `registry.yarnpkg.com`, `registry.npmmirror.com`, `cdn.npmmirror.com`, `pypi.org`, `files.pythonhosted.org`, `pypi.tuna.tsinghua.edu.cn`, `crates.io`, `index.crates.io`, `static.crates.io`, `static.rust-lang.org`, `rsproxy.cn`, `proxy.golang.org`, `sum.golang.org`, `goproxy.cn`, `repo.maven.apache.org`, `repo1.maven.org`, `maven.aliyun.com`, `services.gradle.org`, `plugins.gradle.org`, `rubygems.org`, `github.com`, `codeload.github.com`, `objects.githubusercontent.com`, `raw.githubusercontent.com`, `gitlab.com`, `gitee.com`, `mirrors.aliyun.com`, `mirrors.tuna.tsinghua.edu.cn`. Every other host asks, in every mode.
|
|
175
|
+
- **The rest.** Subagents, workflows, scheduled tasks, MCP and tools registered by plugins ask in read-only and ask mode, and run immediately in auto mode. Leaving the sandbox always asks. While the sandbox is not ready, a command that may change things asks even in auto mode. In ask and auto mode, allow and deny rules in the project config override the defaults above. Read-only mode still cannot edit files or run anything except read-only commands.
|
|
176
|
+
- **Collaboration members.** The leader hands a task to a member without asking. When a member (Claude Code, Codex, OpenCode, or a product with a member adapter) wants to edit files, run commands, reach a website or read files, the rules above decide it; what needs asking shows in the approval bar and a member's question in the question box, both naming the member. Members' commands do not run in MerakCode's OS sandbox (Codex runs them in its own sandbox), and a custom product added as a one-shot command never asks: its own settings decide.
|
|
177
|
+
|
|
178
|
+
| Mode | Good for | What happens |
|
|
179
|
+
| ------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
180
|
+
| Read-only | Designs and plans | No edits, only read-only commands. Still asks before a non-secret read outside the workspace, a secret, or a host off the allowlist |
|
|
181
|
+
| Ask (default) | Everyday work | Edits a workspace file immediately when no path segment starts with `.`. Asks before edits to dot paths, file-changing commands and deletes, reads or edits outside the workspace, secrets, or hosts off the allowlist |
|
|
182
|
+
| Auto | Large projects, when you trust the AI | Edits inside the workspace (including dot paths), file-changing commands and deletes run immediately. Still asks before writes outside, risky commands, secret reads, hosts off the allowlist, or leaving the sandbox |
|
|
183
|
+
|
|
184
|
+
Switch modes next to the input in the desktop app, or press `Shift+Tab`. When it asks, you can allow once, allow for this session, always allow (saved to the project config) or deny.
|
|
185
|
+
|
|
186
|
+
Commands the agent runs also go into an **OS sandbox**: they can only write the workspace, temp folders and package manager caches; they cannot read key folders such as `~/.ssh` or `~/.aws`; they cannot change `.git/hooks` or `.git/config`; and network traffic goes through a local proxy that asks you about hosts off the allowlist that you have not approved. The sandbox is our own code on top of what each OS provides:
|
|
187
|
+
|
|
188
|
+
| System | Built on | What you need to do |
|
|
189
|
+
| ------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
190
|
+
| Windows | A separate low-rights account, NTFS permissions, the firewall | Click "Set up" under Settings → Permissions & security in the desktop app (or run `merak sandbox setup` once) and approve one administrator prompt |
|
|
191
|
+
| Linux | Landlock (kernel 5.13 or newer) | Nothing. Network rules need kernel 6.7 or newer |
|
|
192
|
+
| macOS | The built-in Seatbelt (sandbox-exec) | Nothing |
|
|
193
|
+
|
|
194
|
+
While the sandbox is not ready (for example before setup on Windows), commands that may change things ask first, even in auto mode. For what the sandbox does and does not protect against, see [SECURITY.md](SECURITY.md).
|
|
195
|
+
|
|
196
|
+
## Collaboration groups
|
|
197
|
+
|
|
198
|
+
In a collaboration group MerakCode is the leader, and Claude Code, Codex, OpenCode and other AI coding tools can be members. Say what you want in the group; the leader splits it into tasks for the members, and each replies in the group when it is done.
|
|
199
|
+
|
|
200
|
+
- Create one from New collaboration group in the sidebar, `⌘/Ctrl+G` or the command palette, or copy the members of an existing group.
|
|
201
|
+
- Mention a member with `@` in the input; rename it or change its role and duty in the member column.
|
|
202
|
+
- What members want to do, and what they ask, shows in the approval bar and the question box, decided by the permission mode you chose.
|
|
203
|
+
- Under Settings › Collaboration, turn products on or off, see their versions and paths and who decides their permissions (MerakCode approves for a product with an adapter; a one-shot command decides itself), and add your own. A CLI older than recommended shows how to upgrade it (`claude update`, `codex update`, `opencode upgrade`) and still works. Recommended: Claude Code 2.1.283, Codex 0.164.0, OpenCode 1.19.4 or later.
|
|
204
|
+
- For an AI coding tool without a built-in adapter, click "Have MerakCode write an adapter to connect your own AI coding tool" under Settings › Collaboration, or ask MerakCode in an ordinary conversation to write and register a member adapter with the adapter generator skill (`adapter-generator`). The skill works from the three built-in adapters: a tool that talks the way one of them does gets a copy of it, changed where it differs; any other gets an adapter written after them. You can also write one yourself with [the member adapter section of the SDK guide](docs/sdk/README.en.md#15-member-adapters-adapter).
|
|
205
|
+
|
|
206
|
+
Products can also be set in the config:
|
|
207
|
+
|
|
208
|
+
```jsonc
|
|
209
|
+
{
|
|
210
|
+
"collaboration": {
|
|
211
|
+
"products": {
|
|
212
|
+
// A built-in product needs only the fields you change, such as where its command is or extra arguments
|
|
213
|
+
"codex": { "command": "/opt/codex/bin/codex", "args": ["-c", "model=\"o3\""] },
|
|
214
|
+
// Your own adapter
|
|
215
|
+
"mycli": { "title": "MyCLI", "adapter": "member", "command": "node", "args": ["/path/to/adapter.mjs"] },
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Configuration
|
|
222
|
+
|
|
223
|
+
| Location | Purpose |
|
|
224
|
+
| ------------------------------------------------------ | -------------------------------------------------------------- |
|
|
225
|
+
| `~/.merakcode/merakcode.json` | Global config (model, language, permission rules...) |
|
|
226
|
+
| `<project>/.merakcode/merakcode.json` | Project config, overrides the global one |
|
|
227
|
+
| `<project>/AGENTS.md` | Notes about your project for MerakCode (`CLAUDE.md` works too) |
|
|
228
|
+
| `<project>/.merakcode/agents/`, `skills/`, `commands/` | Custom agents, skills and slash commands |
|
|
229
|
+
|
|
230
|
+
Config files can be plain JSON or JSONC with comments. Add `"$schema"` at the top and your editor will autocomplete and check it:
|
|
231
|
+
|
|
232
|
+
```jsonc
|
|
233
|
+
{
|
|
234
|
+
"$schema": "https://raw.githubusercontent.com/TongTong313/merakcode/main/schema/config.json",
|
|
235
|
+
"model": "anthropic/claude-sonnet-4-5",
|
|
236
|
+
"locale": "en-US",
|
|
237
|
+
"permission": {
|
|
238
|
+
"bash": { "git status": "allow", "rm -rf *": "deny" },
|
|
239
|
+
},
|
|
240
|
+
"sandbox": { "mode": "preferred" },
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
To change the language: in the desktop app, use Settings → General → Language. On the command line, set `"locale"` in the config (`zh-CN` or `en-US`) or the environment variable `MERAKCODE_LOCALE`.
|
|
245
|
+
|
|
246
|
+
## SDK
|
|
247
|
+
|
|
248
|
+
To use MerakCode from your own program, use the TypeScript SDK:
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
npm install @merakcode/sdk
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import { createMerakCode } from "@merakcode/sdk"
|
|
256
|
+
|
|
257
|
+
const merak = await createMerakCode({ cwd: process.cwd() })
|
|
258
|
+
const session = await merak.session()
|
|
259
|
+
for await (const event of session.run("What does this project do?")) {
|
|
260
|
+
if (event.type === "text") process.stdout.write(event.delta)
|
|
261
|
+
}
|
|
262
|
+
await merak.close()
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
See the [SDK guide](docs/sdk/README.en.md) for everything else.
|
|
266
|
+
|
|
267
|
+
## Develop from source
|
|
268
|
+
|
|
269
|
+
You need Node.js 26.12 or newer and pnpm 12.
|
|
270
|
+
|
|
271
|
+
```sh
|
|
272
|
+
git clone https://github.com/TongTong313/merakcode.git
|
|
273
|
+
cd merakcode
|
|
274
|
+
pnpm install
|
|
275
|
+
pnpm hooks:install # check formatting before each commit
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Run from source
|
|
279
|
+
|
|
280
|
+
| To | Run |
|
|
281
|
+
| -------------------------- | -------------------------------------------------------------------------------- |
|
|
282
|
+
| Work on the desktop app | `pnpm --dir apps/desktop/main dev` |
|
|
283
|
+
| Run a command-line command | `pnpm dev run "Explain this project"` |
|
|
284
|
+
| Start only the engine | `pnpm dev serve --port 4096` |
|
|
285
|
+
| Debug the engine | `node --inspect --import ./script/node/register.mjs apps/cli/src/index.ts serve` |
|
|
286
|
+
| Print detailed logs | `pnpm dev serve --print-logs --log-level DEBUG` |
|
|
287
|
+
|
|
288
|
+
**Note**: desktop development reloads the UI as you save and restarts the app when main process code changes. Engine changes do not restart anything: use Help › Restart Local Service, and windows reconnect on their own.
|
|
289
|
+
|
|
290
|
+
`pnpm dev` runs the source directly; there is nothing to build first. Change the code and run it again.
|
|
291
|
+
|
|
292
|
+
### Tests and checks
|
|
293
|
+
|
|
294
|
+
```sh
|
|
295
|
+
pnpm check # formatting, types, dependency boundaries, generated files... run before you commit
|
|
296
|
+
cd packages/engine && pnpm test # each package runs its own tests
|
|
297
|
+
cd apps/cli && pnpm test test/cli/doctor-command.test.ts # a single file
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Packaging
|
|
301
|
+
|
|
302
|
+
```sh
|
|
303
|
+
pnpm --dir apps/cli build --single # CLI release bundle for this machine, in apps/cli/dist/
|
|
304
|
+
pnpm --dir apps/desktop/main package # desktop installer for this machine, in apps/desktop/main/release/
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The CLI ends up at `apps/cli/dist/merakcode-<version>-<platform>/bin/merak` (`merak.cmd` on Windows). Packaging downloads Node and Electron; if that is slow, set `MERAKCODE_NODE_MIRROR` and `ELECTRON_MIRROR` to a closer mirror.
|
|
308
|
+
|
|
309
|
+
### Generated files
|
|
310
|
+
|
|
311
|
+
| If you changed | Run |
|
|
312
|
+
| ------------------ | ------------------------------------------------------- |
|
|
313
|
+
| A server route | `pnpm generate:sdk`, then `pnpm generate:sdk-reference` |
|
|
314
|
+
| A config option | `pnpm generate:schema` |
|
|
315
|
+
| An error code | `pnpm generate:errors` |
|
|
316
|
+
| The SDK public API | `pnpm check:api --write` |
|
|
317
|
+
|
|
318
|
+
### Point the SDK at the engine source
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
const merak = await createMerakCode({
|
|
322
|
+
executablePath: [process.execPath, "--import", "<repo>/script/node/register.mjs", "<repo>/apps/cli/src/index.ts"],
|
|
323
|
+
})
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Layout
|
|
327
|
+
|
|
328
|
+
```text
|
|
329
|
+
apps/cli the merak command; merak serve is the engine, and the desktop app ships the same one
|
|
330
|
+
apps/desktop/main desktop app main process (Electron)
|
|
331
|
+
apps/desktop/renderer desktop app UI (SolidJS)
|
|
332
|
+
packages/engine the engine: sessions, models, tools, permissions, HTTP server
|
|
333
|
+
packages/sandbox the OS sandbox (Windows / Linux / macOS)
|
|
334
|
+
packages/sdk/js TypeScript SDK
|
|
335
|
+
packages/util, log shared helpers and logging
|
|
336
|
+
packages/client-core approval options for the desktop app
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Neither the desktop app nor the command-line commands import engine code. They start a `merak serve` process through the SDK and talk to it over HTTP and an event stream. `pnpm check` enforces this. See [CONTRIBUTING.md](CONTRIBUTING.md) for the rest of the conventions.
|
|
340
|
+
|
|
341
|
+
## When something goes wrong
|
|
342
|
+
|
|
343
|
+
1. If the error has a code (such as `[MRK-2002]`), look it up in the [error code list](docs/errors.md).
|
|
344
|
+
2. Run `merak doctor`; it tells you which part is broken.
|
|
345
|
+
3. Still stuck? Run `merak bug-report` and attach the zip to an [issue](https://github.com/TongTong313/merakcode/issues/new/choose).
|
|
346
|
+
4. To read the logs yourself: `merak logs` shows where they are, `merak logs --tail` follows the newest one.
|
|
347
|
+
|
|
348
|
+
## Security
|
|
349
|
+
|
|
350
|
+
Please do not report security problems in public issues. See [SECURITY.md](SECURITY.md) for how to report them privately.
|
|
351
|
+
|
|
352
|
+
## Contributing
|
|
353
|
+
|
|
354
|
+
Issues and pull requests are welcome; let's make MerakCode better together. See [CONTRIBUTING.md](CONTRIBUTING.md) for the guidelines.
|
|
355
|
+
|
|
356
|
+
## License
|
|
357
|
+
|
|
358
|
+
[MIT](LICENSE)
|
|
359
|
+
|
|
360
|
+
## Thanks
|
|
361
|
+
|
|
362
|
+
Parts of this project are based on code from [opencode](https://github.com/anomalyco/opencode), and we thank them for it. Their license notices are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
MerakCode contains code taken from or based on the open-source projects below. Their licenses ask us to keep
|
|
4
|
+
their copyright notices, so they are reproduced here in full.
|
|
5
|
+
|
|
6
|
+
Release packages also contain `THIRD_PARTY_LICENSES.txt`, which lists every npm package bundled into that
|
|
7
|
+
release together with its license text.
|
|
8
|
+
|
|
9
|
+
## opencode
|
|
10
|
+
|
|
11
|
+
- Project: https://github.com/anomalyco/opencode
|
|
12
|
+
- Used in: the engine (sessions, tools, providers, server)
|
|
13
|
+
- License: MIT
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
MIT License
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2025 opencode
|
|
19
|
+
|
|
20
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
22
|
+
in the Software without restriction, including without limitation the rights
|
|
23
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
25
|
+
furnished to do so, subject to the following conditions:
|
|
26
|
+
|
|
27
|
+
The above copyright notice and this permission notice shall be included in all
|
|
28
|
+
copies or substantial portions of the Software.
|
|
29
|
+
|
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
|
+
SOFTWARE.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## pi-mono
|
|
40
|
+
|
|
41
|
+
- Project: https://github.com/badlogic/pi-mono
|
|
42
|
+
- Used in: the patterns that detect "context window exceeded" errors in `packages/engine/src/provider/error.ts`
|
|
43
|
+
- License: MIT
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
MIT License
|
|
47
|
+
|
|
48
|
+
Copyright (c) 2025 Mario Zechner
|
|
49
|
+
|
|
50
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
51
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
52
|
+
in the Software without restriction, including without limitation the rights
|
|
53
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
54
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
55
|
+
furnished to do so, subject to the following conditions:
|
|
56
|
+
|
|
57
|
+
The above copyright notice and this permission notice shall be included in all
|
|
58
|
+
copies or substantial portions of the Software.
|
|
59
|
+
|
|
60
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
61
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
62
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
63
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
64
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
65
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
66
|
+
SOFTWARE.
|
|
67
|
+
```
|
package/bin/cli-name.cjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command name and npm package names. Lives in bin/ because the npm launcher requires it at startup.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const commandName = "merak"
|
|
6
|
+
|
|
7
|
+
/** npm package id: the main package and the platform package prefix */
|
|
8
|
+
const packageName = "merakcode"
|
|
9
|
+
|
|
10
|
+
function binMap() {
|
|
11
|
+
return { [commandName]: `./bin/${commandName}` }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Platform package: merakcode-<os>-<arch>. Windows is spelled "windows"; npm reserves "win32" for its os field. */
|
|
15
|
+
function platformPackage(platform, arch) {
|
|
16
|
+
return `${packageName}-${platform === "win32" ? "windows" : platform}-${arch}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
commandName,
|
|
21
|
+
packageName,
|
|
22
|
+
binMap,
|
|
23
|
+
platformPackage,
|
|
24
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Deliberately standalone: copied beside the npm launcher, and bundled into desktop.
|
|
2
|
+
const fs = require("node:fs")
|
|
3
|
+
const path = require("node:path")
|
|
4
|
+
const os = require("node:os")
|
|
5
|
+
|
|
6
|
+
function safe(value) {
|
|
7
|
+
return (
|
|
8
|
+
String(value)
|
|
9
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
10
|
+
.slice(0, 80) || "unknown"
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function root() {
|
|
15
|
+
if (process.env.MERAKCODE_LOG_ROOT) return process.env.MERAKCODE_LOG_ROOT.replaceAll("\0", "")
|
|
16
|
+
return path.join(process.env.MERAKCODE_HOME?.replaceAll("\0", "") || path.join(os.homedir(), ".merakcode"), "logs")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Only extracted, bounded identifiers reach disk. Never persist arbitrary stderr, argv, URLs or report payloads.
|
|
20
|
+
function nativeEvidence(text) {
|
|
21
|
+
// Node/V8 fatal errors: heap exhaustion, failed V8 checks, and the native stack trace printed with them
|
|
22
|
+
const runtime = /FATAL ERROR:|# Fatal error in|Native stack trace/.test(text)
|
|
23
|
+
const native = /segmentation fault|access violation/i.test(text)
|
|
24
|
+
return {
|
|
25
|
+
runtime_crash_signature: runtime,
|
|
26
|
+
native_fault_signature: native,
|
|
27
|
+
runtime_version: text.match(/Node\.js v(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/)?.[1],
|
|
28
|
+
fault_address: text.match(/(?:fault at address|access violation at)\s+(0x[0-9a-f]+)/i)?.[1],
|
|
29
|
+
modules_observed:
|
|
30
|
+
runtime || native ? [...new Set(text.match(/[A-Za-z0-9_.-]{1,120}\.(?:dll|node)\b/gi) || [])].slice(0, 30) : [],
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class CrashEvidence {
|
|
35
|
+
constructor(options) {
|
|
36
|
+
const dir = path.join(options.root || root(), ".state", "crash-evidence")
|
|
37
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 })
|
|
38
|
+
this.file = path.join(dir, `${safe(options.component)}-${safe(options.runId)}.json`)
|
|
39
|
+
this.tail = ""
|
|
40
|
+
this.closed = false
|
|
41
|
+
this.data = {
|
|
42
|
+
schema: "merakcode.crash-evidence.v3",
|
|
43
|
+
owner_pid: process.pid,
|
|
44
|
+
component: safe(options.component),
|
|
45
|
+
run_id: safe(options.runId),
|
|
46
|
+
started_at: new Date().toISOString(),
|
|
47
|
+
evidence: nativeEvidence(""),
|
|
48
|
+
}
|
|
49
|
+
this.save()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
save() {
|
|
53
|
+
fs.writeFileSync(this.file, JSON.stringify(this.data), { mode: 0o600 })
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
write(chunk) {
|
|
57
|
+
if (this.closed) return 0
|
|
58
|
+
try {
|
|
59
|
+
// Process bounded windows even if a caller hands us a very large chunk.
|
|
60
|
+
const value = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8")
|
|
61
|
+
for (let offset = 0; offset < value.length; offset += 8192) {
|
|
62
|
+
this.tail = (this.tail + value.slice(offset, offset + 8192)).slice(-32768)
|
|
63
|
+
const next = nativeEvidence(this.tail)
|
|
64
|
+
const previous = this.data.evidence
|
|
65
|
+
this.data.evidence = {
|
|
66
|
+
...previous,
|
|
67
|
+
runtime_crash_signature: previous.runtime_crash_signature || next.runtime_crash_signature,
|
|
68
|
+
native_fault_signature: previous.native_fault_signature || next.native_fault_signature,
|
|
69
|
+
runtime_version: next.runtime_version || previous.runtime_version,
|
|
70
|
+
fault_address: next.fault_address || previous.fault_address,
|
|
71
|
+
modules_observed: [...new Set([...previous.modules_observed, ...next.modules_observed])].slice(0, 30),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (this.data.evidence.runtime_crash_signature || this.data.evidence.native_fault_signature) this.save()
|
|
75
|
+
return value.length
|
|
76
|
+
} catch {
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
close(options = {}) {
|
|
82
|
+
if (this.closed) return
|
|
83
|
+
this.closed = true
|
|
84
|
+
this.tail = ""
|
|
85
|
+
try {
|
|
86
|
+
if (!options.keep) {
|
|
87
|
+
fs.rmSync(this.file, { force: true })
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
this.data.owner_pid = 0
|
|
91
|
+
this.data.exit_code = options.code ?? null
|
|
92
|
+
this.data.signal = options.signal ?? null
|
|
93
|
+
this.save()
|
|
94
|
+
} catch {}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = { CrashEvidence, nativeEvidence }
|
package/bin/merak
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// npm entry point. npm installs only the platform package for this machine (merakcode-<os>-<arch>, see
|
|
4
|
+
// optionalDependencies); find it and run its lib/index.js with its bundled Node.
|
|
5
|
+
// MERAKCODE_BIN_PATH overrides the executable (for debugging).
|
|
6
|
+
|
|
7
|
+
const childProcess = require("child_process")
|
|
8
|
+
const fs = require("fs")
|
|
9
|
+
const path = require("path")
|
|
10
|
+
const os = require("os")
|
|
11
|
+
const crypto = require("crypto")
|
|
12
|
+
const { platformPackage } = require("./cli-name.cjs")
|
|
13
|
+
|
|
14
|
+
function logRoot(env) {
|
|
15
|
+
if (env.MERAKCODE_LOG_ROOT) return env.MERAKCODE_LOG_ROOT.replaceAll("\0", "")
|
|
16
|
+
return path.join(env.MERAKCODE_HOME?.replaceAll("\0", "") || path.join(os.homedir(), ".merakcode"), "logs")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runDirect(command, args, env) {
|
|
20
|
+
const result = childProcess.spawnSync(command, args, { stdio: "inherit", env })
|
|
21
|
+
if (result.error) {
|
|
22
|
+
console.error(result.error.message)
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
process.exit(typeof result.status === "number" ? result.status : 0)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function run(command, args, env) {
|
|
29
|
+
if (process.platform !== "win32") return runDirect(command, args, env)
|
|
30
|
+
// Windows: keep stderr as crash evidence when the process exits abnormally
|
|
31
|
+
const runId = crypto.randomUUID()
|
|
32
|
+
const childEnv = { ...env, MERAKCODE_RUN_ID: runId }
|
|
33
|
+
const evidence = (() => {
|
|
34
|
+
try {
|
|
35
|
+
const helper = fs.existsSync(path.join(__dirname, "crash-evidence.cjs"))
|
|
36
|
+
? path.join(__dirname, "crash-evidence.cjs")
|
|
37
|
+
: path.join(__dirname, "../node_modules/@merakcode/log/src/crash-evidence.cjs")
|
|
38
|
+
const { CrashEvidence } = require(helper)
|
|
39
|
+
return new CrashEvidence({ root: logRoot(childEnv), component: "cli", runId })
|
|
40
|
+
} catch {
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
})()
|
|
44
|
+
// Evidence failure never prevents launching the product.
|
|
45
|
+
let controlled = false
|
|
46
|
+
const child = childProcess.spawn(command, args, {
|
|
47
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
48
|
+
env: childEnv,
|
|
49
|
+
})
|
|
50
|
+
child.stderr.on("data", (chunk) => {
|
|
51
|
+
process.stderr.write(chunk)
|
|
52
|
+
evidence?.write(chunk)
|
|
53
|
+
})
|
|
54
|
+
child.on("error", (error) => {
|
|
55
|
+
evidence?.close()
|
|
56
|
+
console.error(error.message)
|
|
57
|
+
process.exit(1)
|
|
58
|
+
})
|
|
59
|
+
// close, unlike exit, waits for stderr to drain.
|
|
60
|
+
child.on("close", (code, signal) => {
|
|
61
|
+
evidence?.close({ keep: !controlled && (code !== 0 || !!signal), code, signal })
|
|
62
|
+
process.exit(typeof code === "number" ? code : signal ? 1 : 0)
|
|
63
|
+
})
|
|
64
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
65
|
+
process.once(signal, () => {
|
|
66
|
+
controlled = true
|
|
67
|
+
child.kill(signal)
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Walks up from this script looking for node_modules/<platform package> */
|
|
73
|
+
function findPlatformPackage(name) {
|
|
74
|
+
for (let dir = path.dirname(fs.realpathSync(__filename)); ; dir = path.dirname(dir)) {
|
|
75
|
+
const candidate = path.join(dir, "node_modules", name)
|
|
76
|
+
if (fs.existsSync(path.join(candidate, "lib", "index.js"))) return candidate
|
|
77
|
+
if (path.dirname(dir) === dir) return
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const env = { ...process.env }
|
|
82
|
+
const args = process.argv.slice(2)
|
|
83
|
+
|
|
84
|
+
if (process.env.MERAKCODE_BIN_PATH) {
|
|
85
|
+
run(process.env.MERAKCODE_BIN_PATH, args, env)
|
|
86
|
+
} else {
|
|
87
|
+
const name = platformPackage(process.platform, process.arch)
|
|
88
|
+
const pkg = findPlatformPackage(name)
|
|
89
|
+
if (!pkg) {
|
|
90
|
+
console.error(
|
|
91
|
+
`The package for this platform (${name}) is not installed. npm may have skipped optional dependencies; ` +
|
|
92
|
+
`reinstall with: npm install -g merakcode\n` +
|
|
93
|
+
`You can also use the install script or download a release from GitHub.`,
|
|
94
|
+
)
|
|
95
|
+
process.exit(1)
|
|
96
|
+
}
|
|
97
|
+
const node = path.join(pkg, "node", process.platform === "win32" ? "node.exe" : "bin/node")
|
|
98
|
+
// node:ffi (used by the engine) prints an ExperimentalWarning on every start
|
|
99
|
+
run(node, ["--disable-warning=ExperimentalWarning", path.join(pkg, "lib", "index.js"), ...args], env)
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "merakcode",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "MerakCode command line: run tasks, start the engine, ACP for editors",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/TongTong313/merakcode.git",
|
|
9
|
+
"directory": "apps/cli"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"merak": "./bin/merak"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"bin",
|
|
16
|
+
"THIRD_PARTY_NOTICES.md"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18"
|
|
20
|
+
},
|
|
21
|
+
"optionalDependencies": {
|
|
22
|
+
"merakcode-darwin-arm64": "0.1.1",
|
|
23
|
+
"merakcode-darwin-x64": "0.1.1",
|
|
24
|
+
"merakcode-linux-arm64": "0.1.1",
|
|
25
|
+
"merakcode-linux-x64": "0.1.1",
|
|
26
|
+
"merakcode-windows-arm64": "0.1.1",
|
|
27
|
+
"merakcode-windows-x64": "0.1.1"
|
|
28
|
+
}
|
|
29
|
+
}
|