@datename/fastcode-termux 0.0.0-stage → 0.1.6

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.
Files changed (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +400 -2
  3. package/bin/fastcode.mjs +59 -0
  4. package/dist/agent/guards.d.ts +35 -0
  5. package/dist/agent/guards.js +74 -0
  6. package/dist/agent/limits.d.ts +24 -0
  7. package/dist/agent/limits.js +71 -0
  8. package/dist/agent/protocol.d.ts +4 -0
  9. package/dist/agent/protocol.js +126 -0
  10. package/dist/agent/tools.d.ts +1 -0
  11. package/dist/agent/tools.js +377 -0
  12. package/dist/app.d.ts +4 -0
  13. package/dist/app.js +476 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.js +518 -0
  16. package/dist/commands/about.d.ts +8 -0
  17. package/dist/commands/about.js +16 -0
  18. package/dist/commands/agent.d.ts +11 -0
  19. package/dist/commands/agent.js +18 -0
  20. package/dist/commands/clear.d.ts +11 -0
  21. package/dist/commands/clear.js +9 -0
  22. package/dist/commands/config.d.ts +7 -0
  23. package/dist/commands/config.js +24 -0
  24. package/dist/commands/cost.d.ts +9 -0
  25. package/dist/commands/cost.js +13 -0
  26. package/dist/commands/cwd.d.ts +7 -0
  27. package/dist/commands/cwd.js +7 -0
  28. package/dist/commands/exit.d.ts +9 -0
  29. package/dist/commands/exit.js +8 -0
  30. package/dist/commands/help.d.ts +6 -0
  31. package/dist/commands/help.js +18 -0
  32. package/dist/commands/index.d.ts +9 -0
  33. package/dist/commands/index.js +58 -0
  34. package/dist/commands/login.d.ts +16 -0
  35. package/dist/commands/login.js +61 -0
  36. package/dist/commands/logout.d.ts +9 -0
  37. package/dist/commands/logout.js +53 -0
  38. package/dist/commands/model.d.ts +11 -0
  39. package/dist/commands/model.js +30 -0
  40. package/dist/commands/plugin.d.ts +11 -0
  41. package/dist/commands/plugin.js +74 -0
  42. package/dist/commands/provider.d.ts +11 -0
  43. package/dist/commands/provider.js +28 -0
  44. package/dist/commands/reset.d.ts +9 -0
  45. package/dist/commands/reset.js +13 -0
  46. package/dist/commands/skills.d.ts +11 -0
  47. package/dist/commands/skills.js +106 -0
  48. package/dist/commands/system.d.ts +11 -0
  49. package/dist/commands/system.js +20 -0
  50. package/dist/commands/theme.d.ts +11 -0
  51. package/dist/commands/theme.js +22 -0
  52. package/dist/commands/tools.d.ts +7 -0
  53. package/dist/commands/tools.js +29 -0
  54. package/dist/commands/whoami.d.ts +9 -0
  55. package/dist/commands/whoami.js +51 -0
  56. package/dist/config/paths.d.ts +4 -0
  57. package/dist/config/paths.js +59 -0
  58. package/dist/config/store.d.ts +69 -0
  59. package/dist/config/store.js +208 -0
  60. package/dist/config/themes.d.ts +73 -0
  61. package/dist/config/themes.js +77 -0
  62. package/dist/config/trust.d.ts +9 -0
  63. package/dist/config/trust.js +67 -0
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.js +31 -0
  66. package/dist/lib/diagnostics.d.ts +41 -0
  67. package/dist/lib/diagnostics.js +139 -0
  68. package/dist/lib/http.d.ts +13 -0
  69. package/dist/lib/http.js +70 -0
  70. package/dist/lib/markdown.d.ts +1 -0
  71. package/dist/lib/markdown.js +32 -0
  72. package/dist/lib/pkg.d.ts +5 -0
  73. package/dist/lib/pkg.js +27 -0
  74. package/dist/lib/platform.d.ts +7 -0
  75. package/dist/lib/platform.js +57 -0
  76. package/dist/lib/startup.d.ts +6 -0
  77. package/dist/lib/startup.js +25 -0
  78. package/dist/lib/uiMode.d.ts +2 -0
  79. package/dist/lib/uiMode.js +7 -0
  80. package/dist/plugins/manager.d.ts +23 -0
  81. package/dist/plugins/manager.js +101 -0
  82. package/dist/providers/anthropic.d.ts +21 -0
  83. package/dist/providers/anthropic.js +107 -0
  84. package/dist/providers/custom.d.ts +24 -0
  85. package/dist/providers/custom.js +25 -0
  86. package/dist/providers/deepseek.d.ts +24 -0
  87. package/dist/providers/deepseek.js +15 -0
  88. package/dist/providers/google.d.ts +24 -0
  89. package/dist/providers/google.js +19 -0
  90. package/dist/providers/groq.d.ts +24 -0
  91. package/dist/providers/groq.js +20 -0
  92. package/dist/providers/index.d.ts +201 -0
  93. package/dist/providers/index.js +37 -0
  94. package/dist/providers/mistral.d.ts +24 -0
  95. package/dist/providers/mistral.js +19 -0
  96. package/dist/providers/moonshot.d.ts +24 -0
  97. package/dist/providers/moonshot.js +22 -0
  98. package/dist/providers/ollama.d.ts +24 -0
  99. package/dist/providers/ollama.js +22 -0
  100. package/dist/providers/openai.d.ts +24 -0
  101. package/dist/providers/openai.js +25 -0
  102. package/dist/providers/openaiCompatible.d.ts +17 -0
  103. package/dist/providers/openaiCompatible.js +110 -0
  104. package/dist/providers/openrouter.d.ts +24 -0
  105. package/dist/providers/openrouter.js +26 -0
  106. package/dist/providers/qwen.d.ts +24 -0
  107. package/dist/providers/qwen.js +23 -0
  108. package/dist/providers/xai.d.ts +24 -0
  109. package/dist/providers/xai.js +18 -0
  110. package/dist/providers/zhipu.d.ts +24 -0
  111. package/dist/providers/zhipu.js +23 -0
  112. package/dist/session/log.d.ts +29 -0
  113. package/dist/session/log.js +135 -0
  114. package/dist/skills/manager.d.ts +18 -0
  115. package/dist/skills/manager.js +201 -0
  116. package/dist/skills/parser.d.ts +18 -0
  117. package/dist/skills/parser.js +65 -0
  118. package/dist/types.d.ts +146 -0
  119. package/dist/types.js +1 -0
  120. package/dist/ui/Banner.d.ts +5 -0
  121. package/dist/ui/Banner.js +65 -0
  122. package/dist/ui/Message.d.ts +7 -0
  123. package/dist/ui/Message.js +13 -0
  124. package/dist/ui/Prompt.d.ts +10 -0
  125. package/dist/ui/Prompt.js +38 -0
  126. package/dist/ui/Spinner.d.ts +5 -0
  127. package/dist/ui/Spinner.js +33 -0
  128. package/dist/ui/StatusBar.d.ts +10 -0
  129. package/dist/ui/StatusBar.js +19 -0
  130. package/dist/ui/TrustGate.d.ts +5 -0
  131. package/dist/ui/TrustGate.js +26 -0
  132. package/package.json +96 -4
  133. package/src/agent/guards.ts +74 -0
  134. package/src/agent/limits.ts +71 -0
  135. package/src/agent/protocol.ts +126 -0
  136. package/src/agent/tools.ts +377 -0
  137. package/src/app.ts +476 -0
  138. package/src/cli.ts +308 -0
  139. package/src/commands/about.ts +16 -0
  140. package/src/commands/agent.ts +18 -0
  141. package/src/commands/clear.ts +9 -0
  142. package/src/commands/config.ts +24 -0
  143. package/src/commands/cost.ts +13 -0
  144. package/src/commands/cwd.ts +7 -0
  145. package/src/commands/exit.ts +8 -0
  146. package/src/commands/help.ts +18 -0
  147. package/src/commands/index.ts +58 -0
  148. package/src/commands/login.ts +61 -0
  149. package/src/commands/logout.ts +53 -0
  150. package/src/commands/model.ts +30 -0
  151. package/src/commands/plugin.ts +74 -0
  152. package/src/commands/provider.ts +28 -0
  153. package/src/commands/reset.ts +13 -0
  154. package/src/commands/skills.ts +106 -0
  155. package/src/commands/system.ts +20 -0
  156. package/src/commands/theme.ts +22 -0
  157. package/src/commands/tools.ts +29 -0
  158. package/src/commands/whoami.ts +51 -0
  159. package/src/config/paths.ts +59 -0
  160. package/src/config/store.ts +240 -0
  161. package/src/config/themes.ts +77 -0
  162. package/src/config/trust.ts +67 -0
  163. package/src/index.ts +31 -0
  164. package/src/lib/diagnostics.ts +139 -0
  165. package/src/lib/http.ts +70 -0
  166. package/src/lib/markdown.ts +32 -0
  167. package/src/lib/pkg.ts +35 -0
  168. package/src/lib/platform.ts +57 -0
  169. package/src/lib/startup.ts +25 -0
  170. package/src/lib/uiMode.ts +7 -0
  171. package/src/plugins/manager.ts +101 -0
  172. package/src/providers/anthropic.ts +107 -0
  173. package/src/providers/custom.ts +25 -0
  174. package/src/providers/deepseek.ts +15 -0
  175. package/src/providers/google.ts +19 -0
  176. package/src/providers/groq.ts +20 -0
  177. package/src/providers/index.ts +37 -0
  178. package/src/providers/mistral.ts +19 -0
  179. package/src/providers/moonshot.ts +22 -0
  180. package/src/providers/ollama.ts +22 -0
  181. package/src/providers/openai.ts +25 -0
  182. package/src/providers/openaiCompatible.ts +110 -0
  183. package/src/providers/openrouter.ts +26 -0
  184. package/src/providers/qwen.ts +23 -0
  185. package/src/providers/xai.ts +18 -0
  186. package/src/providers/zhipu.ts +23 -0
  187. package/src/session/log.ts +135 -0
  188. package/src/skills/manager.ts +201 -0
  189. package/src/skills/parser.ts +65 -0
  190. package/src/types.ts +143 -0
  191. package/src/ui/Banner.ts +68 -0
  192. package/src/ui/Message.ts +13 -0
  193. package/src/ui/Prompt.ts +38 -0
  194. package/src/ui/Spinner.ts +33 -0
  195. package/src/ui/StatusBar.ts +19 -0
  196. package/src/ui/TrustGate.ts +26 -0
  197. package/tsconfig.json +22 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SimpleLittleDev
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,401 @@
1
- # Temporary Holding Version
1
+ # ⚡ FastCode
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <p align="center">
4
+ <strong>A colorful, fast, terminal-first AI coding assistant.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ Multi-LLM chat • Agent Skills • Slash commands • Themes • Termux-ready
9
+ </p>
10
+
11
+ <p align="center">
12
+ <img alt="Node" src="https://img.shields.io/badge/node-%3E%3D18.17-3c873a?style=for-the-badge&logo=node.js&logoColor=white">
13
+ <img alt="npm" src="https://img.shields.io/badge/npm-@datename%2Ffastcode--termux-cb3837?style=for-the-badge&logo=npm&logoColor=white">
14
+ <img alt="License" src="https://img.shields.io/badge/license-MIT-f59e0b?style=for-the-badge">
15
+ <img alt="Termux" src="https://img.shields.io/badge/Termux-ready-7c3aed?style=for-the-badge&logo=android&logoColor=white">
16
+ </p>
17
+
18
+ ```bash
19
+ npm install -g @datename/fastcode-termux
20
+ fastcode
21
+ ```
22
+
23
+ Short alias included:
24
+
25
+ ```bash
26
+ fc
27
+ ```
28
+
29
+ ---
30
+
31
+ ## 🌈 What Is FastCode?
32
+
33
+ FastCode is a beautiful TUI coding assistant that runs inside your terminal.
34
+ It connects to your favorite AI provider, keeps the workflow command-driven,
35
+ and supports Anthropic-style **Agent Skills** for specialized abilities.
36
+
37
+ It is built for developers who want an AI assistant that feels quick, direct,
38
+ and usable from anywhere: Linux, macOS, Windows, and Android through Termux.
39
+
40
+ ---
41
+
42
+ ## ✨ Highlights
43
+
44
+ | Feature | What You Get |
45
+ | --- | --- |
46
+ | 🎨 Colorful TUI | Big FastCode banner, themes, transcript bubbles, status bar |
47
+ | 🤖 Multi-provider | Anthropic, OpenAI, Gemini, OpenRouter, Groq, DeepSeek, Mistral, Ollama |
48
+ | 🧠 Agent Skills | Install and enable `SKILL.md` powered workflows |
49
+ | 🧩 Plugins | Import always-active plugin packs with bundled skills |
50
+ | 🛠️ Coding Agent | Shell, file editing, grep, patching, and sandboxed local tools |
51
+ | ⚡ Slash commands | Switch models, manage keys, enable skills, inspect config |
52
+ | 📱 Termux-ready | Stable UI mode helps avoid flicker on Android terminals |
53
+ | 🔐 Local config | Keys and preferences stay under `~/.fastcode` |
54
+
55
+ ---
56
+
57
+ ## 🚀 Install
58
+
59
+ ### Install from the source repo (recommended)
60
+
61
+ The repo ships a self-contained bundle at `package/dist/cli.js`, so a plain
62
+ `git clone` runs without `npm install`:
63
+
64
+ ```bash
65
+ git clone https://github.com/dateName/fastcode-termux.git
66
+ cd fastcode-termux
67
+ bash scripts/install.sh
68
+ fastcode
69
+ ```
70
+
71
+ Manual equivalent:
72
+
73
+ ```bash
74
+ git clone https://github.com/dateName/fastcode-termux.git
75
+ cd fastcode-termux/package
76
+ npm install # ⚠️ do not skip
77
+ npm link
78
+ ```
79
+
80
+ ### Global install
81
+
82
+ ```bash
83
+ npm install -g @datename/fastcode-termux
84
+ fastcode
85
+ ```
86
+
87
+ ### Run without installing globally
88
+
89
+ ```bash
90
+ npx @datename/fastcode-termux
91
+ ```
92
+
93
+ ### Start with a prompt
94
+
95
+ ```bash
96
+ fastcode "explain this repository"
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 🔑 Add Your API Key
102
+
103
+ Use environment variables:
104
+
105
+ ```bash
106
+ export ANTHROPIC_API_KEY="sk-ant-..."
107
+ export OPENAI_API_KEY="sk-..."
108
+ export OPENROUTER_API_KEY="sk-or-..."
109
+ ```
110
+
111
+ Or bind a key from inside FastCode — scoped to a specific provider + model (input is masked):
112
+
113
+ ```text
114
+ /login # guided: provider → model → key
115
+ /login openai gpt-4o-mini sk-...
116
+ /login anthropic claude-3-5-sonnet-latest sk-ant-...
117
+ ```
118
+
119
+ Then start chatting:
120
+
121
+ ```bash
122
+ fastcode
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 🧩 Providers
128
+
129
+ | Provider | Default Model | Auth |
130
+ | --- | --- | --- |
131
+ | `anthropic` | `claude-3-5-sonnet-latest` | `ANTHROPIC_API_KEY` or `CLAUDE_API_KEY` |
132
+ | `openai` | `gpt-4o-mini` | `OPENAI_API_KEY` |
133
+ | `google` | `gemini-1.5-flash` | `GEMINI_API_KEY` or `GOOGLE_API_KEY` |
134
+ | `openrouter` | `anthropic/claude-3.5-sonnet` | `OPENROUTER_API_KEY` |
135
+ | `groq` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |
136
+ | `deepseek` | `deepseek-chat` | `DEEPSEEK_API_KEY` |
137
+ | `mistral` | `mistral-small-latest` | `MISTRAL_API_KEY` |
138
+ | `ollama` | `llama3.2` | Local, no API key required |
139
+
140
+ Switch anytime:
141
+
142
+ ```text
143
+ /provider openai
144
+ /model gpt-4o-mini
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 🪄 Agent Skills
150
+
151
+ FastCode can install and inject Anthropic-style skills into the system prompt.
152
+
153
+ ```text
154
+ /skills search pdf
155
+ /skills install pdf
156
+ /skills install anthropics/skills/pdf
157
+ /skills install https://example.com/my-skill/SKILL.md
158
+ /skills enable pdf
159
+ /skills list
160
+ /skills info pdf
161
+ ```
162
+
163
+ Installed skills live here:
164
+
165
+ ```text
166
+ ~/.fastcode/skills/<name>/SKILL.md
167
+ ```
168
+
169
+ ---
170
+
171
+ ## 🛠️ Coding Agent
172
+
173
+ FastCode can act as a local coding agent. Agent mode is enabled by default and
174
+ works with any provider, including local Ollama models.
175
+
176
+ ```text
177
+ /agent status
178
+ /agent on
179
+ /agent off
180
+ /tools
181
+ /cwd
182
+ ```
183
+
184
+ Available tools include:
185
+
186
+ ```text
187
+ shell, pwd, read_file, read_many, write_file, append_file, apply_patch,
188
+ replace_in_file, list_files, grep, stat_path, make_dir, copy_file,
189
+ move_path, delete_file
190
+ ```
191
+
192
+ Tools run inside a sandbox rooted at the directory where you start FastCode.
193
+ File tools cannot access paths outside that root. Shell commands run with:
194
+
195
+ ```text
196
+ FASTCODE_SANDBOX=1
197
+ FASTCODE_SANDBOX_ROOT=<current-working-directory>
198
+ ```
199
+
200
+ Example:
201
+
202
+ ```bash
203
+ cd ~/my-project
204
+ fastcode "run the tests, find the failing file, patch it, and verify the fix"
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 🧩 Plugins
210
+
211
+ Plugins are always-active behavior packs. A plugin folder can contain:
212
+
213
+ ```text
214
+ my-plugin/
215
+ ├── PLUGIN.md
216
+ └── skills/
217
+ └── reviewer/
218
+ └── SKILL.md
219
+ ```
220
+
221
+ Import and enable a plugin:
222
+
223
+ ```text
224
+ /plugin import ./my-plugin reviewer
225
+ /plugin list
226
+ /plugin info reviewer
227
+ /plugin disable reviewer
228
+ /plugin enable reviewer
229
+ /plugin remove reviewer
230
+ ```
231
+
232
+ Installed plugins live under:
233
+
234
+ ```text
235
+ ~/.fastcode/plugins/
236
+ ```
237
+
238
+ ---
239
+
240
+ ## 🎮 Slash Commands
241
+
242
+ | Command | Action |
243
+ | --- | --- |
244
+ | `/help` | Show command list |
245
+ | `/agent [on/off/status]` | Toggle local coding-agent tools |
246
+ | `/tools` | Show available coding tools |
247
+ | `/cwd` | Show agent sandbox root |
248
+ | `/plugin ...` | Import and manage always-active plugin packs |
249
+ | `/provider [id]` | List or switch provider |
250
+ | `/model [id]` | List or switch model |
251
+ | `/login [provider] [model] [key]` | Bind an API key to a provider + model (guided when omitted) |
252
+ | `/logout <provider> [model]` | Remove a scoped key (`--all` for the whole provider) |
253
+ | `/skills ...` | Search, install, enable, disable, list skills |
254
+ | `/theme [id]` | Switch theme |
255
+ | `/cost` | Show token and cost usage |
256
+ | `/system [text]` | Show or update system prompt |
257
+ | `/whoami` | Show configured provider keys |
258
+ | `/config` | Print config and paths |
259
+ | `/clear` | Clear conversation |
260
+ | `/reset` | Reset config |
261
+ | `/about` | Show version and platform |
262
+ | `/exit` | Quit |
263
+
264
+ Keyboard controls:
265
+
266
+ ```text
267
+ Esc cancel streaming
268
+ Ctrl+C press twice to quit
269
+ ```
270
+
271
+ ---
272
+
273
+ ## 🎨 Themes
274
+
275
+ ```text
276
+ /theme fastcode
277
+ /theme neon
278
+ /theme sunset
279
+ /theme matrix
280
+ /theme mono
281
+ ```
282
+
283
+ Want the calmest terminal experience?
284
+
285
+ ```bash
286
+ FASTCODE_STABLE_UI=1 fastcode
287
+ ```
288
+
289
+ Termux enables stable UI automatically.
290
+
291
+ ---
292
+
293
+ ## 📱 Termux
294
+
295
+ Install Node.js first:
296
+
297
+ ```bash
298
+ pkg install nodejs
299
+ npm install -g @datename/fastcode-termux
300
+ fastcode
301
+ ```
302
+
303
+ If the command is not found, check your npm global binary path:
304
+
305
+ ```bash
306
+ npm bin -g
307
+ echo "$PATH"
308
+ ```
309
+
310
+ FastCode stores config inside your home directory:
311
+
312
+ ```text
313
+ ~/.fastcode/
314
+ ├── config.json
315
+ ├── auth.json
316
+ ├── skills/
317
+ ├── plugins/
318
+ ├── cache/
319
+ ├── sessions/
320
+ └── logs/
321
+ ```
322
+
323
+ You can move that root with:
324
+
325
+ ```bash
326
+ FASTCODE_HOME=/path/to/fastcode fastcode
327
+ ```
328
+
329
+ ---
330
+
331
+ ## 🛠️ Development
332
+
333
+ ```bash
334
+ git clone https://github.com/dateName/fastcode-termux
335
+ cd FastCode
336
+ npm install
337
+ npm run dev
338
+ ```
339
+
340
+ Quality checks:
341
+
342
+ ```bash
343
+ npm run check
344
+ ```
345
+
346
+ Or run each step:
347
+
348
+ ```bash
349
+ npm test
350
+ npm run typecheck
351
+ npm run lint
352
+ npm run build
353
+ ```
354
+
355
+ Run the built CLI:
356
+
357
+ ```bash
358
+ node ./bin/fastcode.mjs
359
+ ```
360
+
361
+ ---
362
+
363
+ ## 📦 Publish Notes
364
+
365
+ The package exposes two global commands:
366
+
367
+ ```json
368
+ {
369
+ "bin": {
370
+ "fastcode": "./bin/fastcode.mjs",
371
+ "fc": "./bin/fastcode.mjs"
372
+ }
373
+ }
374
+ ```
375
+
376
+ Publish public scoped releases with:
377
+
378
+ ```bash
379
+ npm publish --access public
380
+ ```
381
+
382
+ ---
383
+
384
+ ## Safety, sessions and limits (0.1.6)
385
+
386
+ | Feature | Behaviour | Override |
387
+ | --- | --- | --- |
388
+ | Project trust | First run in a folder asks before agent tools load; the list lives in ~/.fastcode/trusted.json | fastcode trust / untrust / trusted, FASTCODE_TRUST_ALL=1 |
389
+ | Dangerous-command guard | rm -rf, del /f, rmdir /s, format / mkfs / diskpart, dd if=, writes to /dev/sd, shutdown / reboot / poweroff and fork bombs are refused before execution | FASTCODE_ALLOW_DANGEROUS=1, FASTCODE_SHELL_ALLOWLIST, FASTCODE_SHELL_DENY_EXTRA |
390
+ | Unified tool-output cap | Output is truncated while it is produced, not sliced afterwards (default 30000 characters) | FASTCODE_TOOL_OUTPUT_LIMIT |
391
+ | Session log | Append-only JSONL in ~/.fastcode/sessions, resumable after a crash (cache cap 256MB by default) | fastcode sessions, fastcode resume, FASTCODE_SESSION_LOG=0, FASTCODE_SESSION_CACHE_MB |
392
+
393
+ ## 🙏 Credits
394
+
395
+ - **SimpleLittleDev** — author of the original FastCode TUI; the npm package
396
+ `@simplelittledev/fastcode` and its credit belong to them.
397
+ - All upstream dependency authors (Ink, React, meow, cfonts, marked, chalk, ...).
398
+
399
+ ## 📜 License
400
+
401
+ MIT © SimpleLittleDev
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ // FastCode CLI shim.
3
+ //
4
+ // Resolution order:
5
+ // 1. dist/cli.js — self-contained esbuild bundle (committed to git: works
6
+ // after a plain `git clone`, no `npm install` required)
7
+ // 2. dist/index.js — tsc output (needs node_modules)
8
+ // 3. src/index.ts — dev fallback via tsx
9
+ import { fileURLToPath, pathToFileURL } from "node:url";
10
+ import { dirname, join } from "node:path";
11
+ import { existsSync } from "node:fs";
12
+
13
+ const here = dirname(fileURLToPath(import.meta.url));
14
+ const bundleEntry = join(here, "..", "dist", "cli.js");
15
+ const distEntry = join(here, "..", "dist", "index.js");
16
+ const srcEntry = [join(here, "..", "src", "index.ts"), join(here, "..", "src", "index.tsx")].find((p) => existsSync(p));
17
+
18
+ const MISSING_DEPS_HELP = `
19
+ ╭─────────────────────────────────────────────╮
20
+ │ ⚠️ FastCode 缺少依赖包 │
21
+ ╰─────────────────────────────────────────────╯
22
+
23
+ 请选择以下任一方式修复:
24
+
25
+ 【方式一】一键安装(推荐)
26
+ bash scripts/install.sh
27
+
28
+ 【方式二】手动安装依赖
29
+ cd package && npm install
30
+
31
+ 【方式三】下载便携版
32
+ https://github.com/dateName/fastcode-termux/releases
33
+ `;
34
+
35
+ async function run() {
36
+ try {
37
+ if (existsSync(bundleEntry)) {
38
+ await import(pathToFileURL(bundleEntry).href);
39
+ } else if (existsSync(distEntry)) {
40
+ await import(pathToFileURL(distEntry).href);
41
+ } else if (srcEntry) {
42
+ // Local dev fallback — let users `node ./bin/fastcode.mjs` from the repo
43
+ const { register } = await import("node:module");
44
+ register("tsx/esm", import.meta.url);
45
+ await import(pathToFileURL(srcEntry).href);
46
+ } else {
47
+ console.error("FastCode build artifacts not found. Did you run `npm run build`?");
48
+ process.exit(1);
49
+ }
50
+ } catch (err) {
51
+ if (err && err.code === "ERR_MODULE_NOT_FOUND") {
52
+ console.error(MISSING_DEPS_HELP);
53
+ process.exit(1);
54
+ }
55
+ throw err;
56
+ }
57
+ }
58
+
59
+ run();
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Dangerous-command guard.
3
+ *
4
+ * Blocks destructive shell patterns before execution. Word-boundary escapes
5
+ * are written as character classes so the intent is identical without
6
+ * boundary syntax.
7
+ *
8
+ * Overrides:
9
+ * FASTCODE_ALLOW_DANGEROUS=1 bypass the deny list (reported in output)
10
+ * FASTCODE_SHELL_ALLOWLIST=a;b only commands matching these regexes run
11
+ * FASTCODE_SHELL_DENY_EXTRA=x;y extra regexes to deny
12
+ * FASTCODE_RESTRICT_TO_WORKSPACE=1 also reject ../ and .. escapes
13
+ */
14
+ export declare const DEFAULT_DENY_PATTERNS: string[];
15
+ export declare const FORK_BOMB_MARKERS: string[];
16
+ /**
17
+ * Decide whether a shell command may run.
18
+ * Returns { allow: true } or { allow: false, output: explanation }.
19
+ */
20
+ export declare function evaluateShellCommand(command: any): {
21
+ allow: boolean;
22
+ output: any;
23
+ bypassed: boolean;
24
+ pattern?: undefined;
25
+ } | {
26
+ allow: boolean;
27
+ pattern: string;
28
+ output: string;
29
+ bypassed?: undefined;
30
+ } | {
31
+ allow: boolean;
32
+ output: string;
33
+ bypassed?: undefined;
34
+ pattern?: undefined;
35
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Dangerous-command guard.
3
+ *
4
+ * Blocks destructive shell patterns before execution. Word-boundary escapes
5
+ * are written as character classes so the intent is identical without
6
+ * boundary syntax.
7
+ *
8
+ * Overrides:
9
+ * FASTCODE_ALLOW_DANGEROUS=1 bypass the deny list (reported in output)
10
+ * FASTCODE_SHELL_ALLOWLIST=a;b only commands matching these regexes run
11
+ * FASTCODE_SHELL_DENY_EXTRA=x;y extra regexes to deny
12
+ * FASTCODE_RESTRICT_TO_WORKSPACE=1 also reject ../ and .. escapes
13
+ */
14
+ export const DEFAULT_DENY_PATTERNS = [
15
+ "(^|[^a-z])rm +-[rf]{1,2}([^a-z]|$)",
16
+ "(^|[^a-z])del +/[fq]([^a-z]|$)",
17
+ "(^|[^a-z])rmdir +/s([^a-z]|$)",
18
+ "(^|[^a-z-])(format|mkfs|diskpart)([^a-z]|$)",
19
+ "(^|[^a-z])dd +if=",
20
+ "> */dev/sd",
21
+ "(^|[^a-z])(shutdown|reboot|poweroff)([^a-z]|$)",
22
+ ];
23
+ export const FORK_BOMB_MARKERS = [":(){", ":|:&"];
24
+ function enabled(name) {
25
+ const value = process.env[name];
26
+ if (value === undefined)
27
+ return false;
28
+ return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
29
+ }
30
+ function splitList(value) {
31
+ return (value ?? "").split(/[;,]/).map((entry) => entry.trim()).filter(Boolean);
32
+ }
33
+ function matches(lower, pattern) {
34
+ try {
35
+ return new RegExp(pattern).test(lower);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * Decide whether a shell command may run.
43
+ * Returns { allow: true } or { allow: false, output: explanation }.
44
+ */
45
+ export function evaluateShellCommand(command) {
46
+ const cmd = String(command ?? "").trim();
47
+ const lower = cmd.toLowerCase();
48
+ if (enabled("FASTCODE_ALLOW_DANGEROUS"))
49
+ return { allow: true, output: undefined, bypassed: true };
50
+ const deny = DEFAULT_DENY_PATTERNS.concat(splitList(process.env["FASTCODE_SHELL_DENY_EXTRA"]));
51
+ for (const pattern of deny) {
52
+ if (matches(lower, pattern)) {
53
+ return {
54
+ allow: false,
55
+ pattern,
56
+ output: "Error: blocked by the safety guard (dangerous pattern: " + pattern + "). " +
57
+ "Set FASTCODE_ALLOW_DANGEROUS=1 to override.",
58
+ };
59
+ }
60
+ }
61
+ for (const marker of FORK_BOMB_MARKERS) {
62
+ if (lower.includes(marker))
63
+ return { allow: false, output: "Error: blocked by the safety guard (fork bomb pattern)." };
64
+ }
65
+ const allowlist = splitList(process.env["FASTCODE_SHELL_ALLOWLIST"]);
66
+ if (allowlist.length > 0 && !allowlist.some((pattern) => matches(lower, pattern)))
67
+ return { allow: false, output: "Error: blocked by the safety guard (not in FASTCODE_SHELL_ALLOWLIST)." };
68
+ if (enabled("FASTCODE_RESTRICT_TO_WORKSPACE")) {
69
+ const backslash = String.fromCharCode(92);
70
+ if (cmd.includes("../") || cmd.includes(".." + backslash))
71
+ return { allow: false, output: "Error: blocked by the safety guard (path traversal)." };
72
+ }
73
+ return { allow: true, output: undefined };
74
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Single source of truth for how much tool output reaches the model.
3
+ *
4
+ * Output is bounded while it is produced, not by slicing a finished string
5
+ * afterwards, so a runaway command or a huge directory listing cannot grow
6
+ * without limit. Override the cap with FASTCODE_TOOL_OUTPUT_LIMIT (characters).
7
+ */
8
+ export declare const DEFAULT_TOOL_OUTPUT_LIMIT = 30000;
9
+ export declare function toolOutputLimit(): number;
10
+ /**
11
+ * Bounded text accumulator.
12
+ *
13
+ * mode "head" keeps the first N characters (listings, search hits);
14
+ * mode "tail" keeps the last N (command logs, where the error is last).
15
+ * trimEnd()/toString() mimic a plain string so callers stay simple.
16
+ */
17
+ export declare function createOutputBuffer(limit?: number, mode?: string): {
18
+ readonly full: boolean;
19
+ push(chunk: any): void;
20
+ line(value: any): void;
21
+ value(): string;
22
+ trimEnd(): string;
23
+ toString(): string;
24
+ };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Single source of truth for how much tool output reaches the model.
3
+ *
4
+ * Output is bounded while it is produced, not by slicing a finished string
5
+ * afterwards, so a runaway command or a huge directory listing cannot grow
6
+ * without limit. Override the cap with FASTCODE_TOOL_OUTPUT_LIMIT (characters).
7
+ */
8
+ export const DEFAULT_TOOL_OUTPUT_LIMIT = 30000;
9
+ export function toolOutputLimit() {
10
+ const raw = Number(process.env["FASTCODE_TOOL_OUTPUT_LIMIT"]);
11
+ return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : DEFAULT_TOOL_OUTPUT_LIMIT;
12
+ }
13
+ /**
14
+ * Bounded text accumulator.
15
+ *
16
+ * mode "head" keeps the first N characters (listings, search hits);
17
+ * mode "tail" keeps the last N (command logs, where the error is last).
18
+ * trimEnd()/toString() mimic a plain string so callers stay simple.
19
+ */
20
+ export function createOutputBuffer(limit = toolOutputLimit(), mode = "head") {
21
+ const NL = String.fromCharCode(10);
22
+ let text = "";
23
+ let dropped = 0;
24
+ const buffer = {
25
+ get full() {
26
+ return text.length >= limit;
27
+ },
28
+ push(chunk) {
29
+ const value = String(chunk);
30
+ if (mode === "tail") {
31
+ text += value;
32
+ if (text.length > limit) {
33
+ const over = text.length - limit;
34
+ dropped += over;
35
+ text = text.slice(over);
36
+ }
37
+ return;
38
+ }
39
+ if (text.length >= limit) {
40
+ dropped += value.length;
41
+ return;
42
+ }
43
+ const room = limit - text.length;
44
+ if (value.length <= room) {
45
+ text += value;
46
+ }
47
+ else {
48
+ text += value.slice(0, room);
49
+ dropped += value.length - room;
50
+ }
51
+ },
52
+ line(value) {
53
+ if (text.length > 0)
54
+ buffer.push(NL);
55
+ buffer.push(value);
56
+ },
57
+ value() {
58
+ if (dropped <= 0)
59
+ return text;
60
+ const note = "[" + dropped + " more characters omitted]";
61
+ return mode === "tail" ? note + NL + text : text + NL + note;
62
+ },
63
+ trimEnd() {
64
+ return buffer.value().trimEnd();
65
+ },
66
+ toString() {
67
+ return buffer.value();
68
+ },
69
+ };
70
+ return buffer;
71
+ }
@@ -0,0 +1,4 @@
1
+ export declare function parseToolCalls(text: any): any[];
2
+ export declare function stripToolCalls(text: any): any;
3
+ export declare function formatToolResults(results: any): string;
4
+ export declare const AGENT_SYSTEM_PROMPT: string;