[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-105323":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":12,"contributorsCount":12,"subscribersCount":12,"size":12,"stars1d":14,"stars7d":14,"stars30d":14,"stars90d":12,"forks30d":12,"starsTrendScore":15,"compositeScore":16,"rankGlobal":9,"rankLanguage":9,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":18,"hasPages":18,"topics":20,"createdAt":9,"pushedAt":9,"updatedAt":27,"readmeContent":28,"aiSummary":9,"trendingCount":12,"starSnapshotCount":12,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},105323,"Mountains","pollenkun\u002FMountains","pollenkun","A coding agent engine and CLI with cache-aware context management.",null,"TypeScript",68,0,52,5,15,49,"Apache License 2.0",false,"main",[21,22,23,24,25,26],"coding-agent","deepseek","glm","kimi","prompt-caching","typescript","2026-11-01 00:14:15","# Mountains Preview 1\n\nEnglish | [中文](README.zh-CN.md)\n\nMountains is a coding agent: an engine plus a single-command CLI. Give it a task and a directory; it reads code, edits it, runs commands, and exits when done.\n\nPreview 1 is a technical experiment, not an everyday tool: there is no interactive interface or multi-turn conversation. We are publishing it to show how the context management and tool design below perform on real tasks. A desktop app comes with Preview 2.\n\n## Results\n\nOne model (DeepSeek V4.1 Flash, reasoning effort high), the same 12 bug-fix tasks from real repositories, 2 runs per task, 24 runs in total.\n\n![Runs solved, total cost and total time](assets\u002Fbenchmark-en.svg)\n\nThese results were measured at the [`preview-1`](https:\u002F\u002Fgithub.com\u002Fpollenkun\u002FMountains\u002Ftree\u002Fpreview-1) tag. Later fixes did not change the system prompt or tool descriptions the model sees, and were not re-measured. None of the 24 runs reached 60% of the context window, so the later change to compaction at 90% does not affect these results.\n\n| System | Version | Solved | Cost (CNY) | Time (min) |\n|---|---|---|---|---|\n| **Mountains** | Preview 1 | 19\u002F24 | **3.72** | **50.4** |\n| [OpenCode](https:\u002F\u002Fgithub.com\u002Fsst\u002Fopencode) | 1.18.32 | 19\u002F24 | 3.98 | 65.1 |\n| [Pi](https:\u002F\u002Fgithub.com\u002Fbadlogic\u002Fpi-mono) | 0.87.1 | 19\u002F24 | 4.68 | 72.0 |\n| [DeepSeek Harness](https:\u002F\u002Fgithub.com\u002Fdeepseek-ai\u002Fdeepseek-harness) | 0.2.0 | **20\u002F24** | 6.68 | 115.3 |\n\nIn short: about as many tasks solved as the other three, at the lowest cost and in the least time.\n\n### Tasks\n\n\"Solved\" per task is how many of its 2 runs succeeded.\n\n| Task | Language | Difficulty | Problem | Mountains | OpenCode | Pi | DeepSeek Harness |\n|---|---|---|---|---|---|---|---|\n| [pallets\u002Fflask#5014](https:\u002F\u002Fgithub.com\u002Fpallets\u002Fflask\u002Fpull\u002F5014) | Python | Ordinary | An empty Blueprint name should raise an error | 2 | 2 | 2 | 2 |\n| [psf\u002Frequests#6028](https:\u002F\u002Fgithub.com\u002Fpsf\u002Frequests\u002Fpull\u002F6028) | Python | Ordinary | Proxy authentication returns 407 on Python 3.8.12 | 2 | 2 | 2 | 2 |\n| [astropy\u002Fastropy#14995](https:\u002F\u002Fgithub.com\u002Fastropy\u002Fastropy\u002Fpull\u002F14995) | Python | Ordinary | NDDataRef mask propagation fails when one operand has no mask | 2 | 2 | 2 | 2 |\n| [pydata\u002Fxarray#7393](https:\u002F\u002Fgithub.com\u002Fpydata\u002Fxarray\u002Fpull\u002F7393) | Python | Ordinary | `stack` casts an int32 coordinate to int64 | 2 | 2 | 2 | 2 |\n| [immutable-js\u002Fimmutable-js#2005](https:\u002F\u002Fgithub.com\u002Fimmutable-js\u002Fimmutable-js\u002Fpull\u002F2005) | JavaScript | Hard | OrderedSet equality and hashCode are wrong | 2 | 1 | 1 | 2 |\n| [thlorenz\u002Fdoctoc#328](https:\u002F\u002Fgithub.com\u002Fthlorenz\u002Fdoctoc\u002Fpull\u002F328) | JavaScript | Ordinary | Text such as `h#` in a heading causes an invalid regular expression | 0 | 0 | 0 | 0 |\n| [cthackers\u002Fadm-zip#559](https:\u002F\u002Fgithub.com\u002Fcthackers\u002Fadm-zip\u002Fpull\u002F559) | JavaScript | Ordinary | addLocalFolderPromise fails with an absolute path on macOS | 2 | 2 | 2 | 2 |\n| [rollup\u002Frollup#6041](https:\u002F\u002Fgithub.com\u002Frollup\u002Frollup\u002Fpull\u002F6041) | JavaScript | Hard | The `in` optimization in 4.46 breaks styled-components | 0 | 0 | 0 | 0 |\n| [kepano\u002Fdefuddle#243](https:\u002F\u002Fgithub.com\u002Fkepano\u002Fdefuddle\u002Fpull\u002F243) | TypeScript | Ordinary | Empty tables with no text are kept in the output | 2 | 2 | 2 | 2 |\n| [stleary\u002FJSON-java#995](https:\u002F\u002Fgithub.com\u002Fstleary\u002FJSON-java\u002Fpull\u002F995) | Java | Ordinary | With keepStrings, `\u003Ct>null\u003C\u002Ft>` is parsed as null | 1 | 2 | 2 | 2 |\n| [google\u002Fgson#1093](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgson\u002Fpull\u002F1093) | Java | Ordinary | In lenient mode, `value(double)` rejects NaN and Infinity | 2 | 2 | 2 | 2 |\n| [gin-gonic\u002Fgin#1805](https:\u002F\u002Fgithub.com\u002Fgin-gonic\u002Fgin\u002Fpull\u002F1805) | Go | Ordinary | With StaticFS, one 404 is logged twice | 2 | 2 | 2 | 2 |\n\nTasks come from SWE-bench Verified, SWE-bench Multilingual and SWE-bench-Live MultiLang. Difficulty is our own rating of how much code a fix requires understanding.\n\n### How we tested\n\n- **Model:** all four systems used DeepSeek V4.1 Flash, reasoning effort high, at most 32,000 output tokens per request.\n- **Task input:** the agent received only the original issue text and the repository at the corresponding commit.\n- **Grading:** the hidden tests that came with the fix, plus the repository's existing regression tests; a run counts as solved only if all pass. The agent cannot see the hidden tests.\n- **Environment:** the same Mac, the same sandbox and launch method. Cost cap per run: 2 CNY for ordinary tasks, 4 CNY for hard ones.\n- **Cost:** computed from the usage DeepSeek reported and its official off-peak prices (per million tokens: cache hit 0.02 CNY, cache miss 1 CNY, output 4 CNY).\n- **Time:** from agent process start to exit, summed over 24 runs.\n- **Other systems:** each ran in its normal headless mode with its default capabilities; nothing was turned off.\n\n### Caveats\n\n- **This is the author's own test.** We built the task set, the grader and the environment ourselves.\n- **The prompt was tuned on these 12 tasks.** Mountains' system prompt and tool notes were written after the author had seen earlier results on these tasks. This favors Mountains, so the results describe its performance on these tasks only; they are not an independent benchmark.\n- **Small sample.** 12 tasks, 2 runs each: one run is about 4 percentage points.\n- **Different run dates.** The other three systems ran on 2026-10-06, Mountains on 2026-10-11. Both days used the same off-peak prices.\n- **Two tasks were solved by none of the four** (doctoc, rollup).\n\n## Design\n\n### Context\n\n- **From 60% of the window: lossless folding.** The program decides which old tool results the model will not need again: those superseded by a later read or edit, those whose same call later succeeded again, failures that later succeeded on retry, and results from requests finished before the last two user requests. Each becomes a one-line notice; the original is archived and can be retrieved. Results fold in batches so the prompt cache is broken rarely.\n- **From 90%: the model writes a summary.** When lossless folding is not enough, the model summarizes everything earlier, the user's earlier messages and answers included; the originals are archived and the model can retrieve the exact wording. That request reuses the cached prefix. If it fails, the program writes a factual record instead.\n- **Always kept verbatim:** the newest request, the most recent work, and results the model has not seen yet. Lossless folding at 60% never touches user messages or the final answer of each turn.\n- **No budget.** The model is not given a token allowance.\n\n### Tools\n\nSix tools: `query_plan` (search, list and read files in one call), `file_read`, `file_edit`, `file_write`, `command_run`, and `context_expand` (retrieve a folded original). In addition, `session_search` searches this session's history and `task_note` lets the model record its working state.\n\n## Usage\n\nRequires Node.js 22.19 or later, npm, Git, and [ripgrep](https:\u002F\u002Fgithub.com\u002FBurntSushi\u002Fripgrep) (`rg`). Git stores file checkpoints.\n\nLinux, macOS and Windows are supported. CI checks each of them with Node.js 22.19 and 24.\n\n- **Linux, macOS:** Bash is also required. Minimal Linux images may need it installed separately; process cleanup needs access to `\u002Fproc` on Linux.\n- **Windows 10\u002F11:** install Git for Windows, including Git Bash, and keep the built-in Windows PowerShell available. Start from PowerShell, cmd, or Git Bash.\n- **WSL:** install and run Linux Node, Git, rg, and Bash inside WSL. Do not mix in Windows Node.\n\nThe example below uses DeepSeek. Its Bash commands work on Linux, macOS, and Git Bash on Windows; PowerShell commands follow below. Download the repository and install its dependencies:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fpollenkun\u002FMountains.git\ncd Mountains\nnpm ci\n```\n\nSet your API key and cumulative spending cap. Replace `your-key` with your DeepSeek API key:\n\n```bash\nexport DEEPSEEK_API_KEY=\"your-key\"\nexport MOUNTAINS_BUDGET=10\n```\n\n`MOUNTAINS_BUDGET` caps the total spent across all runs (in CNY). Create `config.json` to cap each run at 2 CNY:\n\n```bash\ncat > config.json \u003C\u003C'JSON'\n{ \"billingCurrency\": \"CNY\", \"limits\": { \"maxCost\": 2 } }\nJSON\n```\n\nCreate a disposable example directory. Its `add` function deliberately subtracts instead of adding:\n\n```bash\nmkdir demo-workspace\ncat > demo-workspace\u002Fadd.cjs \u003C\u003C'JS'\nexports.add = (a, b) => a - b;\nJS\n```\n\nMountains edits the files in `--workspace` directly. Run it in a directory under version control, or one you can throw away.\n\n`--workspace` sets the task directory; it is not an operating-system sandbox. Commands run with your user account's permissions and can read or modify files outside that directory and access the network. The default policy automatically allows ordinary commands, file changes and network access without asking each time. Run untrusted tasks in an isolated environment; a disposable directory alone does not protect other files on your computer.\n\nRun the task. This step calls DeepSeek and incurs model charges:\n\n```bash\nnpm run mountains -- run --task \"Fix add in add.cjs so it returns the sum of two numbers\" --workspace .\u002Fdemo-workspace --config config.json\n```\n\nWhen it finishes, the terminal shows the result, estimated cost and recording directory. Check that the example was fixed:\n\n```bash\nnode -e \"require('node:assert\u002Fstrict').equal(require('.\u002Fdemo-workspace\u002Fadd.cjs').add(2, 3), 5); console.log('OK')\"\n```\n\nAn `OK` result means this example passes. For your own project, replace `--workspace` with its path and `--task` with your request. Run all the commands above from the Mountains repository directory.\n\n### Windows PowerShell\n\nIf you use PowerShell, run these commands from the Mountains repository directory. Node writes the files to avoid the BOM added by Windows PowerShell 5.1:\n\n```powershell\nnpm.cmd ci\n$env:DEEPSEEK_API_KEY = \"your-key\"\n$env:MOUNTAINS_BUDGET = \"10\"\nnode -e \"require('node:fs').writeFileSync('config.json', JSON.stringify({billingCurrency:'CNY',limits:{maxCost:2}}))\"\nnode -e \"require('node:fs').mkdirSync('demo-workspace',{recursive:true});require('node:fs').writeFileSync('demo-workspace\u002Fadd.cjs','exports.add = (a, b) => a - b;\\n')\"\nnpm.cmd run mountains -- run --task \"Fix add in add.cjs so it returns the sum of two numbers\" --workspace .\u002Fdemo-workspace --config config.json\n```\n\nThe last command calls DeepSeek, incurs model charges, and edits the example directory directly.\n\nThe command tool uses Bash syntax for `shellScript`. Direct `argv` calls need a native executable; run `npm.cmd` and `.bat` files through `cmd.exe \u002Fc` or Git Bash. Windows PowerShell manages child processes. If system policy blocks it, the command tool cannot run.\n\n### Commands and background processes\n\n`command_run` runs temporary commands. It attempts to clean up their processes when the command ends, times out, or is cancelled. Start long-running services in a separately managed terminal or service, rather than relying on a trailing `&` to keep them alive.\n\nWindows uses Job Objects. On Linux with an available user-systemd manager and support for `systemd-run --expand-environment=no`, the command enters its own scope before starting, and cleanup checks that the whole scope is empty. This adds no Python runtime requirement and does not configure system services for you.\n\nmacOS and Linux without usable user-systemd have best-effort cleanup. Results explicitly mark cleanup as unconfirmed; descendants that detach too early can survive. Exit code 0 does not mean every background process has stopped. This is not a sandbox, and cleanup is not guaranteed after the host process is forcibly killed or the system crashes.\n\n### Recordings and spending\n\nRecordings, replays, archives, and the spending ledger go in `.mountains` under your home directory (`%USERPROFILE%\\.mountains` on Windows). Set `MOUNTAINS_HOME` to use another directory. A ledger path set in the config or through `--spend-ledger` takes precedence. Run output, the spending ledger, checkpoints, and archives must stay outside the task workspace.\n\nWhen `MOUNTAINS_HOME` is set, if `~\u002F.mountains\u002Fspend.jsonl` already holds a ledger and the new directory has none, the CLI stops first. Move the old ledger over, or keep its original path with `--spend-ledger`, so cumulative spending does not restart at zero.\n\nThe compile cache is separate: Linux uses `$XDG_CACHE_HOME` (default `~\u002F.cache`), macOS uses `~\u002FLibrary\u002FCaches`, and Windows uses `%LOCALAPPDATA%`, followed by `mountains\u002Fnode-compile-cache`. An unavailable cache does not prevent startup.\n\nCheckpoints also save Git-ignored files before file tools change them. Changes to ignored files made by commands may not be recoverable. Keep a separate backup of important files.\n\n### Skills\n\nA skill is a folder holding `SKILL.md` in the [Agent Skills](https:\u002F\u002Fagentskills.io\u002Fspecification) format, so skills written for other agents work as they are:\n\n```markdown\n---\nname: changelog\ndescription: Write changelog entries in the project's format. Use when writing or editing CHANGELOG.\n---\n\nUse Keep a Changelog headings…\n```\n\nMountains looks for skills here, and the first one found wins a name: the project's `.mountains\u002Fskills` and `.agents\u002Fskills` (from the workspace up to the repository root), the folders listed in `skills.dirs` in the config, `~\u002F.mountains\u002Fskills`, and `~\u002F.agents\u002Fskills`.\n\nThe model sees only each skill's name and description, and loads the full instructions and bundled files with the `skill` tool when it needs them. A task that starts with `\u002Fskill-name` brings that skill in directly, for example `--task \"\u002Fchangelog write the 2.1 entry\"`. With no skills installed, the model sees exactly the tools and prompt of the version measured above.\n\nProject skills come from the repository and may tell the model to run scripts, so by default someone has to approve them before they load; a CLI run has no one to ask, so it does not load them. Allow the ones you trust by name in the config; `*` matches any characters:\n\n```json\n{ \"skills\": { \"permissions\": { \"changelog\": \"allow\", \"deploy-*\": \"deny\" } } }\n```\n\n### Checks\n\nHelp requires no API key and sends no model request:\n\n```bash\nnpm run mountains -- --help\n```\n\nCheck the code. These tests run locally and make no paid model calls:\n\n```bash\nnpm run check\n```\n\nRun only the office, daily-work and coding scenarios:\n\n```bash\nnpm run test:scenarios\n```\n\nThese scenarios use temporary CSV, Markdown, text and source files, with real file operations, commands, checkpoints and recovery. Model responses come from fixed scripts or a local mock server. They do not measure real-model task success or test Word\u002FExcel binary formats. Multi-request and session-restoration tests use the engine API; the Preview 1 CLI remains single-task.\n\nThe tests also need Python 3: `python3` on Linux\u002FmacOS, or `python` on Windows. Use `MOUNTAINS_PYTHON` to select another installed interpreter. Windows must allow symlink creation for those tests to run. POSIX permissions, special filenames, and macOS sandbox tests run only on the relevant systems.\n\n## License\n\n[Apache License 2.0](LICENSE)\n\n## Support Mountains\n\nIf Mountains has been useful to you, you're welcome to buy me a coffee via the WeChat appreciation code below. Your support helps me keep building and improving Mountains.\n\nSupport is entirely optional. Ideas, bug reports, and contributions are just as welcome. Thank you for being part of Mountains!\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fwechat-appreciation.jpg\" alt=\"WeChat appreciation code — support Mountains\" width=\"320\" \u002F>\n\u003C\u002Fp>\n",2,"2026-10-31 04:26:27","CREATED_QUERY"]