flint-agent 1.14.0
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/.env.example +108 -0
- package/CHANGELOG.md +55 -0
- package/FEATURES.md +298 -0
- package/LICENSE +21 -0
- package/README.md +435 -0
- package/bin/flint.js +47 -0
- package/config/classifier-prompt.md +218 -0
- package/config/models-curated.json +4 -0
- package/config/providers.json +74 -0
- package/package.json +92 -0
- package/patches/ink+6.8.0.patch +78 -0
- package/profiles/desktop.md +65 -0
- package/profiles/generic.md +20 -0
- package/profiles/marketer.md +20 -0
- package/profiles/profiles.json +34 -0
- package/profiles/ux-reviewer.md +25 -0
- package/src/agent/agent.js +1743 -0
- package/src/agent/auto.js +346 -0
- package/src/agent/backoff.js +143 -0
- package/src/agent/compression.js +310 -0
- package/src/agent/content-resolver.js +180 -0
- package/src/agent/flow-controller.js +309 -0
- package/src/agent/intent-manifest.js +231 -0
- package/src/agent/intent-timeout.js +46 -0
- package/src/agent/intent.js +633 -0
- package/src/agent/knowledge.js +114 -0
- package/src/agent/learning.js +180 -0
- package/src/agent/modes.js +187 -0
- package/src/agent/outcome-ask.js +91 -0
- package/src/agent/project-context.js +76 -0
- package/src/agent/prompt-budget.js +117 -0
- package/src/agent/reflection-extractor.js +140 -0
- package/src/agent/steering.js +86 -0
- package/src/agent/supervisor.js +430 -0
- package/src/agent/swap.js +443 -0
- package/src/agent/system-prompt.js +446 -0
- package/src/agent/time-stamp.js +48 -0
- package/src/agent/tool-guard.js +201 -0
- package/src/agent/toolcall-text.js +162 -0
- package/src/agent/usage.js +297 -0
- package/src/agent/vision.js +94 -0
- package/src/agent/watchdog.js +139 -0
- package/src/agent/workspace-changes.js +177 -0
- package/src/api/address.js +14 -0
- package/src/api/client.js +280 -0
- package/src/api/server.js +535 -0
- package/src/api/stream-pipe.js +113 -0
- package/src/app-state.js +39 -0
- package/src/bootstrap.js +501 -0
- package/src/bus/drain-loop.js +497 -0
- package/src/bus/index.js +270 -0
- package/src/bus/plugins.js +65 -0
- package/src/child-idle.js +14 -0
- package/src/cli.js +118 -0
- package/src/commands/commands.js +1297 -0
- package/src/commands/registry.js +132 -0
- package/src/components/App.js +491 -0
- package/src/components/CarefulMenu.js +145 -0
- package/src/components/HistoryWriter.js +86 -0
- package/src/components/LineInput.js +69 -0
- package/src/components/LiveZone.js +294 -0
- package/src/components/OverlayMenu.js +179 -0
- package/src/components/SystemPanel.js +156 -0
- package/src/components/Table.js +54 -0
- package/src/config.js +249 -0
- package/src/free-models.js +230 -0
- package/src/index.js +1111 -0
- package/src/input-handler.js +13 -0
- package/src/input-text.js +123 -0
- package/src/launcher.js +129 -0
- package/src/logging/api-log.js +95 -0
- package/src/logging/chat-log-follower.js +113 -0
- package/src/logging/chat-log.js +15 -0
- package/src/logging/log-collector.js +182 -0
- package/src/logging/logger.js +112 -0
- package/src/logging/tool-log.js +20 -0
- package/src/mcp-client.js +314 -0
- package/src/memory/conversation-digest.js +113 -0
- package/src/memory/extract-facts.js +98 -0
- package/src/memory/facts.js +181 -0
- package/src/memory/inbox.js +63 -0
- package/src/memory/markdown.js +38 -0
- package/src/memory/patterns.js +185 -0
- package/src/memory/project.js +66 -0
- package/src/memory/reflections.js +74 -0
- package/src/memory/retrieval.js +84 -0
- package/src/memory/rules.js +105 -0
- package/src/memory/session-facts.js +125 -0
- package/src/memory/skills.js +191 -0
- package/src/memory/sqlite-store.js +653 -0
- package/src/memory/store.js +208 -0
- package/src/memory/tools.js +196 -0
- package/src/memory/user-model.js +86 -0
- package/src/message-handler.js +775 -0
- package/src/model-check.js +218 -0
- package/src/plugins/loader.js +120 -0
- package/src/plugins/manager.js +88 -0
- package/src/production-env.js +22 -0
- package/src/profiles.js +42 -0
- package/src/providers/adapters/anthropic.js +270 -0
- package/src/providers/adapters/openai.js +120 -0
- package/src/providers/keys-dpapi.js +41 -0
- package/src/providers/keys-fallback.js +31 -0
- package/src/providers/keys.js +132 -0
- package/src/providers/models.js +154 -0
- package/src/providers/registry.js +56 -0
- package/src/providers/state.js +56 -0
- package/src/registry.js +96 -0
- package/src/restart.js +29 -0
- package/src/sandbox/backend.js +130 -0
- package/src/security/api-auth.js +132 -0
- package/src/security/audit.js +98 -0
- package/src/security/child-policy.js +41 -0
- package/src/security/command-guard.js +173 -0
- package/src/security/content-fence.js +250 -0
- package/src/security/content-validator.js +132 -0
- package/src/security/index.js +143 -0
- package/src/security/network-guard.js +126 -0
- package/src/security/pairing.js +180 -0
- package/src/security/path-guard.js +140 -0
- package/src/security/persona-guard.js +67 -0
- package/src/security/policies.js +452 -0
- package/src/security/safety-constants.js +34 -0
- package/src/security/watchdog.js +107 -0
- package/src/sessions.js +130 -0
- package/src/spend.js +97 -0
- package/src/startup-watchdog.js +59 -0
- package/src/stdio/args.js +71 -0
- package/src/stdio/guard.js +59 -0
- package/src/stdio/protocol.js +167 -0
- package/src/stdio/run.js +106 -0
- package/src/stdio/session.js +180 -0
- package/src/store/agent-slice.js +306 -0
- package/src/store/dataset-slice.js +73 -0
- package/src/store/index.js +22 -0
- package/src/store/process-slice.js +135 -0
- package/src/store/session-slice.js +191 -0
- package/src/store/ui-slice.js +119 -0
- package/src/tasks/db.js +184 -0
- package/src/tasks/queries.js +589 -0
- package/src/tools/agent-tools.js +473 -0
- package/src/tools/checkpoint.js +152 -0
- package/src/tools/command-approvals.js +180 -0
- package/src/tools/dataset.js +50 -0
- package/src/tools/filesystem.js +682 -0
- package/src/tools/inbox-tools.js +48 -0
- package/src/tools/mesh.js +135 -0
- package/src/tools/own-env.js +136 -0
- package/src/tools/permissions.js +681 -0
- package/src/tools/plugin-tools.js +123 -0
- package/src/tools/process-tools.js +595 -0
- package/src/tools/registry.js +307 -0
- package/src/tools/swap-tools.js +72 -0
- package/src/tools/system.js +662 -0
- package/src/tools/tasks.js +532 -0
- package/src/tools/tool-search.js +171 -0
- package/src/ui/header.js +140 -0
- package/src/ui/input-cursor.js +23 -0
- package/src/ui/last-line.js +25 -0
- package/src/ui/line-edit.js +135 -0
- package/src/ui/output.js +399 -0
- package/src/ui/paste-tokens.js +131 -0
- package/src/ui/prompt-attention.js +134 -0
- package/src/ui/render-options.js +13 -0
- package/src/ui/replay.js +94 -0
- package/src/ui/splash.js +49 -0
- package/src/ui/status-level.js +36 -0
- package/src/ui/tool-ledger.js +203 -0
- package/src/ui/window-title.js +150 -0
- package/src/update.js +205 -0
- package/system.md +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/flint-mark-dark.svg">
|
|
3
|
+
<img alt="Flint" src="assets/flint-mark-light.svg" width="270">
|
|
4
|
+
</picture>
|
|
5
|
+
|
|
6
|
+
# Flint Agent
|
|
7
|
+
|
|
8
|
+
[](https://github.com/dklymentiev/flint-agent/actions/workflows/ci.yml)
|
|
9
|
+
[](https://www.npmjs.com/package/flint-agent)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
**A lightweight AI agent for your terminal, built to work well with any
|
|
14
|
+
model, cheap and free ones included.** It reads files, writes code, runs
|
|
15
|
+
commands, searches the web, uses MCP servers and remembers what you taught
|
|
16
|
+
it. On OpenRouter's free tier, `/model free` picks the free models that can
|
|
17
|
+
call tools and falls back to another when one is busy.
|
|
18
|
+
|
|
19
|
+
It works with OpenRouter, OpenAI, Anthropic, Google, Groq, Together or a
|
|
20
|
+
local Ollama, and installs as a single npm package: no Python, no Docker, no
|
|
21
|
+
background service.
|
|
22
|
+
|
|
23
|
+
Project page: https://klymentiev.com/projects/flint
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What it does
|
|
28
|
+
|
|
29
|
+
Ask Flint the way you would ask a colleague:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
> Read my project and tell me what it does
|
|
33
|
+
> Find all TODO comments and make a plan to fix them
|
|
34
|
+
> Write a Python script that converts CSV to JSON, then run it
|
|
35
|
+
> Take a screenshot of the desktop and click on Chrome
|
|
36
|
+
> Search the web for React best practices in 2026
|
|
37
|
+
> Remember that our deploy day is Wednesday
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Flint picks the tools, asks before anything risky (by default: deleting a
|
|
41
|
+
file, destructive or one-way commands such as `git push`, child agents and
|
|
42
|
+
MCP tools), and shows each tool call as it happens.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
Needs Node.js 22.12 or newer.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -g flint-agent
|
|
52
|
+
flint
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or from the repository:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/dklymentiev/flint-agent.git
|
|
59
|
+
cd flint-agent
|
|
60
|
+
npm install
|
|
61
|
+
npm link # makes the `flint` command point at this folder
|
|
62
|
+
flint
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
On the first run a short setup picks a provider, takes your API key and asks
|
|
66
|
+
how careful Flint should be. `flint --version` checks the install.
|
|
67
|
+
|
|
68
|
+
**`flint` not found on Windows?** npm puts its commands in the folder that
|
|
69
|
+
`npm prefix -g` prints (usually `%APPDATA%\npm`), and that folder has to be on
|
|
70
|
+
your PATH. Add it under Settings, System, About, Advanced system settings,
|
|
71
|
+
Environment Variables, then open a new terminal. `npm start` in the Flint
|
|
72
|
+
folder works either way.
|
|
73
|
+
|
|
74
|
+
**Updates.** Flint says when a newer version is out, at most once a day, and
|
|
75
|
+
`/update` installs it and restarts in the same session. It never updates on
|
|
76
|
+
its own, and it refuses to overwrite local changes. See
|
|
77
|
+
[docs/self-update.md](docs/self-update.md).
|
|
78
|
+
|
|
79
|
+
### Command line
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
flint # start a new session
|
|
83
|
+
flint --last # continue the last session
|
|
84
|
+
flint --model google/gemini-2.5-flash # pick a model
|
|
85
|
+
flint --provider anthropic # use Anthropic directly
|
|
86
|
+
flint --profile desktop # desktop automation profile
|
|
87
|
+
flint --headless --task "Fix the bug" --cwd ./my-project
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Free OpenRouter models: run Flint on the free tier
|
|
93
|
+
|
|
94
|
+
Flint runs on [OpenRouter](https://openrouter.ai)'s free tier: free models
|
|
95
|
+
from several vendors behind one API key, through OpenRouter's free LLM API.
|
|
96
|
+
|
|
97
|
+
1. Create a free key at openrouter.ai.
|
|
98
|
+
2. Run `flint` and paste the key when it asks.
|
|
99
|
+
3. Type `/model free auto`.
|
|
100
|
+
|
|
101
|
+
Most free models cannot call tools, and the ones that can are often
|
|
102
|
+
rate-limited. Flint keeps only the free models that can call tools (the
|
|
103
|
+
`:free` variants and the other zero-priced ones), ranks them by current speed
|
|
104
|
+
and uptime from OpenRouter's public stats, and hands OpenRouter the best one
|
|
105
|
+
with two fallbacks from other vendors, so a busy model passes the request to
|
|
106
|
+
the next. Flint counts today's free requests in the footer. `/model free`
|
|
107
|
+
shows the list; `/model test` scores any model on small agent tasks. More in
|
|
108
|
+
[docs/free-mode.md](docs/free-mode.md).
|
|
109
|
+
|
|
110
|
+
### Can I use Flint for free?
|
|
111
|
+
|
|
112
|
+
Yes. Create a free OpenRouter key, paste it when Flint asks, then run
|
|
113
|
+
`/model free auto`. Flint itself is free and open source (MIT).
|
|
114
|
+
|
|
115
|
+
### Which free OpenRouter models work with Flint?
|
|
116
|
+
|
|
117
|
+
The free models that can call tools, because an agent works through tools.
|
|
118
|
+
Flint reads that from OpenRouter's model list and ranks them live by speed and
|
|
119
|
+
uptime, so the choice follows OpenRouter as its free list changes.
|
|
120
|
+
|
|
121
|
+
### How does `/model free auto` pick a model?
|
|
122
|
+
|
|
123
|
+
It ranks the free tool-calling models by current throughput and uptime,
|
|
124
|
+
takes the best, and sets two fallbacks from other vendors. When the first is
|
|
125
|
+
rate-limited or down, OpenRouter passes the request to the next.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## How it works
|
|
130
|
+
|
|
131
|
+
You type a message. Flint sends it to the model with a set of tools. The
|
|
132
|
+
model decides which tools to call, Flint runs them (asking first when the
|
|
133
|
+
action is risky) and loops until the task is done.
|
|
134
|
+
|
|
135
|
+
The conversation is ordinary terminal output: scroll and select it with your
|
|
136
|
+
terminal. Only a few rows at the bottom are live: what Flint is doing, the
|
|
137
|
+
background processes it started, the input line and one status line. Each
|
|
138
|
+
tool call leaves one line, and each turn ends with a receipt: tools used,
|
|
139
|
+
files changed, tokens in and out, time and cost.
|
|
140
|
+
|
|
141
|
+
**Esc** stops the running turn; pressed again, it stops background processes,
|
|
142
|
+
newest first. **Ctrl+C** twice exits. **Up/Down** recalls earlier input.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Features
|
|
147
|
+
|
|
148
|
+
### Any model, including free ones
|
|
149
|
+
|
|
150
|
+
| Provider | Default model |
|
|
151
|
+
|---|---|
|
|
152
|
+
| [OpenRouter](https://openrouter.ai) (default) | google/gemini-2.5-flash |
|
|
153
|
+
| OpenAI | gpt-4o |
|
|
154
|
+
| Anthropic | claude-sonnet-4-6 |
|
|
155
|
+
| Google Gemini (OpenAI-compatible endpoint) | gemini-3-flash-preview |
|
|
156
|
+
| Groq | llama-3.3-70b-versatile |
|
|
157
|
+
| Together | meta-llama/Llama-3.3-70B-Instruct-Turbo |
|
|
158
|
+
| Ollama (local) | llama3.2 |
|
|
159
|
+
|
|
160
|
+
Switch with `/provider` and `/model`, also in the middle of a conversation.
|
|
161
|
+
Providers are defined in `config/providers.json`; your own copy in
|
|
162
|
+
`~/.flint/providers.json` adds or overrides them. API keys are stored
|
|
163
|
+
encrypted (DPAPI on Windows, AES-256-GCM elsewhere).
|
|
164
|
+
|
|
165
|
+
**Free models.** See [Free OpenRouter models](#free-openrouter-models-run-flint-on-the-free-tier)
|
|
166
|
+
above. `/model test` runs small agent tasks with checked answers on any model
|
|
167
|
+
and saves the score: [docs/model-check.md](docs/model-check.md).
|
|
168
|
+
|
|
169
|
+
### Tools, and more through MCP
|
|
170
|
+
|
|
171
|
+
Built-in tools cover files (read, write, edit, search, with checkpoints and
|
|
172
|
+
undo), shell commands and background processes, the web (fetch a page,
|
|
173
|
+
search), persistent memory, task plans, child agents, and desktop control
|
|
174
|
+
through an MCP desktop server.
|
|
175
|
+
|
|
176
|
+
Any [MCP](https://modelcontextprotocol.io) server adds its tools: mail,
|
|
177
|
+
chat, databases, your own APIs. Configure servers in `MCP_SERVERS` or in a
|
|
178
|
+
`.mcp.json` file in the working folder:
|
|
179
|
+
|
|
180
|
+
```env
|
|
181
|
+
MCP_SERVERS=gmail|http|http://localhost:9090/mcp,my-db|stdio|~/my-db-server mcp
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
With many MCP tools, Flint lists them by name in a `tool_search` tool and
|
|
185
|
+
loads the ones the model asks for, so they do not fill every request.
|
|
186
|
+
|
|
187
|
+
### Long sessions that stay affordable
|
|
188
|
+
|
|
189
|
+
Every call to the model sends the whole conversation again. Flint keeps that
|
|
190
|
+
down in three ways:
|
|
191
|
+
|
|
192
|
+
- **Tool search**, above.
|
|
193
|
+
- **Swap.** Big and old tool results, and old turns of a long conversation,
|
|
194
|
+
move to the session's folder on disk. One line stays in their place
|
|
195
|
+
(`[swap #37 · page · <url> · 11 KB · "<title>" · turn 12 · swap_read 37]`),
|
|
196
|
+
and the agent reads them back with `swap_read` when it needs them. Nothing
|
|
197
|
+
is lost. See [docs/context-swap.md](docs/context-swap.md).
|
|
198
|
+
- **Compression.** The last resort: old tool results are cut to a one-line
|
|
199
|
+
summary. This one does lose text.
|
|
200
|
+
|
|
201
|
+
One switch decides how early they start:
|
|
202
|
+
|
|
203
|
+
| | economy | normal (default) | generous |
|
|
204
|
+
|---|---|---|---|
|
|
205
|
+
| For | paid models, long sessions | most work | capable models with big windows, quality first |
|
|
206
|
+
| MCP tools offered whole | up to 10 | up to 30 | up to 200 |
|
|
207
|
+
| Swap wakes up at | ~16k-32k tokens of context | ~48k-96k | near the window's edge |
|
|
208
|
+
| Compression starts at | a quarter of the window (max 64k) | half the window (max 128k) | 80% of the window |
|
|
209
|
+
| Old conversation goes to swap at | 40% of the window (max 150k) | 60% (max 300k) | 85% |
|
|
210
|
+
| Big result goes to swap when awake | over 2 KB | over 4 KB | over 16 KB |
|
|
211
|
+
| Token-saving advice to the model | yes | no | no |
|
|
212
|
+
|
|
213
|
+
Below those thresholds nothing is moved or shortened. `/spend` shows the
|
|
214
|
+
modes; `/spend economy`, `/spend normal`, `/spend generous` (or `e`, `n`, `g`)
|
|
215
|
+
switch and are remembered; `FLINT_SPEND` in the environment wins. Money
|
|
216
|
+
limits are separate: `AGENT_MAX_COST` per message and `AGENT_SESSION_BUDGET`
|
|
217
|
+
per session, both unlimited by default. See [docs/spend-modes.md](docs/spend-modes.md).
|
|
218
|
+
|
|
219
|
+
### Sessions
|
|
220
|
+
|
|
221
|
+
Sessions are saved as you go. `/resume` picks a recent one to continue,
|
|
222
|
+
`/new` starts a fresh one, and restarts (`/restart`, `/update`) keep the
|
|
223
|
+
session you were in.
|
|
224
|
+
|
|
225
|
+
### Autonomous mode
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
> /auto Refactor the auth module to use JWT, update all tests, write migration docs
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Flint writes a plan, works through it task by task, keeps progress in SQLite
|
|
232
|
+
(`/plan`, `/tasks`), and stops when it is done or when it reaches your
|
|
233
|
+
budget. `/continue` resumes unfinished work.
|
|
234
|
+
|
|
235
|
+
### Persistent memory
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
> Remember that our API rate limit is 5000 req/min
|
|
239
|
+
> What's our rate limit?
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Memory survives across sessions and is protected by an HMAC integrity
|
|
243
|
+
check: a memory file changed outside Flint is detected and not loaded.
|
|
244
|
+
|
|
245
|
+
### Profiles
|
|
246
|
+
|
|
247
|
+
| Profile | For | Context |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `generic` (default) | coding, files, general tasks | full history, compressed when it grows |
|
|
250
|
+
| `desktop` | GUI automation, browser | last 15 messages |
|
|
251
|
+
| `marketer` | content, research, analysis | last 15 messages |
|
|
252
|
+
| `ux-reviewer` | UI and UX reviews | full history |
|
|
253
|
+
|
|
254
|
+
`/profile <name>` switches. Add your own: a markdown file in `profiles/` and
|
|
255
|
+
an entry in `profiles/profiles.json`.
|
|
256
|
+
|
|
257
|
+
### Plugins
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
/install <git url or path>
|
|
261
|
+
/plugins
|
|
262
|
+
/uninstall <name>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
A plugin can add tools, hooks and commands.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Safety
|
|
270
|
+
|
|
271
|
+
Flint runs commands and edits files on your machine, so it asks first. On the
|
|
272
|
+
first run you choose how often (`/careful` changes it later):
|
|
273
|
+
|
|
274
|
+
- **safe**: asks before every change to files and every command;
|
|
275
|
+
- **normal** (default): edits files and runs ordinary commands, but asks
|
|
276
|
+
before deleting a file, destructive commands (`rm -r`, `git reset --hard`),
|
|
277
|
+
one-way ones (pushing to git, publishing, uploads, mail), child agents and
|
|
278
|
+
MCP tools;
|
|
279
|
+
- **permissive**: asks only before deleting a file and reconnecting an MCP
|
|
280
|
+
server.
|
|
281
|
+
|
|
282
|
+
Reading a secret file (`.env`, SSH keys, credentials) asks at every level,
|
|
283
|
+
and some commands are refused at every level. Around that sit further guards:
|
|
284
|
+
filesystem paths can be limited (`AGENT_ALLOWED_PATHS`), requests to internal
|
|
285
|
+
network addresses are refused, outside content is screened for prompt
|
|
286
|
+
injection, child agents inherit the blocked paths and cannot nest deeper than
|
|
287
|
+
five levels, and every tool call goes to an audit log.
|
|
288
|
+
`/permissions`, `/allow <tool>`, `/deny <tool>` and `/confirm <tool>` set
|
|
289
|
+
single tools; `/allow-all` skips confirmations for the session.
|
|
290
|
+
|
|
291
|
+
These guards reduce risk; they do not make running an AI agent with your
|
|
292
|
+
permissions safe in every case. Read what it asks before you answer. See
|
|
293
|
+
[SECURITY.md](SECURITY.md) to report a problem.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Running Flint from other programs
|
|
298
|
+
|
|
299
|
+
### Headless
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
flint --headless --task "Fix the failing test in auth.test.js" --cwd ./project --budget 0.50
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Runs one task and prints JSON on stdout:
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{"response": "Fixed the test...", "cost": 0.034, "tokens": 12500}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Stdio (stream-json subprocess)
|
|
312
|
+
|
|
313
|
+
A host that drives an agent CLI as a long-lived subprocess can drive Flint the
|
|
314
|
+
same way, with the same flags and the same JSON lines:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
flint --print --verbose --model stealth/space-bunny-alpha \
|
|
318
|
+
--input-format stream-json --output-format stream-json \
|
|
319
|
+
--session-id 0b7c4c8e-1f2a-4d3b-9c8d-1234567890ab
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Write `{"type":"user","message":{"role":"user","content":"..."}}` lines to
|
|
323
|
+
stdin; read `system`, `assistant`, `user` (tool results) and `result` lines
|
|
324
|
+
from stdout. The working folder's `CLAUDE.md` files and `.mcp.json` are read.
|
|
325
|
+
See [docs/stdio-mode.md](docs/stdio-mode.md).
|
|
326
|
+
|
|
327
|
+
### HTTP API
|
|
328
|
+
|
|
329
|
+
A running Flint listens on `127.0.0.1:3000`. A program pairs once (you confirm
|
|
330
|
+
a PIN in the console) and then sends messages, reads status and history,
|
|
331
|
+
manages the queue and stops tasks:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
curl -X POST 127.0.0.1:3000/pair/request -d '{"agentName":"my-script"}'
|
|
335
|
+
# Flint shows a PIN; the program sends it to /pair/confirm and gets a token,
|
|
336
|
+
# once: it stays valid across restarts until /paired revoke my-script.
|
|
337
|
+
curl -X POST 127.0.0.1:3000/message \
|
|
338
|
+
-H "Authorization: Bearer <token>" \
|
|
339
|
+
-d '{"content":"What files changed today?"}'
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Commands
|
|
345
|
+
|
|
346
|
+
| Command | What it does |
|
|
347
|
+
|---|---|
|
|
348
|
+
| `/help` | all commands and keys |
|
|
349
|
+
| `/model [id]`, `/model free`, `/model test` | show or switch the model; free models; score a model |
|
|
350
|
+
| `/provider [name]`, `/key` | switch provider; manage API keys |
|
|
351
|
+
| `/resume`, `/new`, `/sessions`, `/load <id>` | sessions |
|
|
352
|
+
| `/spend [level]` | economy, normal or generous |
|
|
353
|
+
| `/careful` | how often Flint asks: safe, normal, permissive |
|
|
354
|
+
| `/auto <task>`, `/continue`, `/plan`, `/tasks` | autonomous work and its plan |
|
|
355
|
+
| `/rewind [N or all]` | undo file changes made in this session |
|
|
356
|
+
| `/tools [n]`, `/sys`, `/budget` | recent tool calls; model, cost and context; spending |
|
|
357
|
+
| `/ps`, `/logs <id>`, `/kill <id>` | background processes |
|
|
358
|
+
| `/mcp`, `/plugins` | MCP servers, plugins |
|
|
359
|
+
| `/memory` | memory stats (`/memory clear` empties it) |
|
|
360
|
+
| `/update`, `/restart` | install a newer version; restart, same session |
|
|
361
|
+
| `exit` | save and quit |
|
|
362
|
+
|
|
363
|
+
### Keys
|
|
364
|
+
|
|
365
|
+
| Key | Action |
|
|
366
|
+
|---|---|
|
|
367
|
+
| `Esc` | clear the input; stop the turn; then stop background processes, newest first |
|
|
368
|
+
| `Ctrl+C` | stop the turn; twice within 2 s exits |
|
|
369
|
+
| `Up` / `Down` | input history |
|
|
370
|
+
| `Alt+V` | paste a picture (or text) from the clipboard as `[Image #N]` |
|
|
371
|
+
| `Ctrl+U`, `Ctrl+W` | clear the line, delete a word |
|
|
372
|
+
|
|
373
|
+
`Ctrl+V` is the terminal's own paste: text works, but with a picture in the
|
|
374
|
+
clipboard most terminals send nothing, so use `Alt+V`.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Configuration
|
|
379
|
+
|
|
380
|
+
Everything is set in a `.env` file or environment variables; see
|
|
381
|
+
[`.env.example`](.env.example) for the full list with descriptions. The ones
|
|
382
|
+
most people touch:
|
|
383
|
+
|
|
384
|
+
| Variable | Default | What it does |
|
|
385
|
+
|---|---|---|
|
|
386
|
+
| `OPENROUTER_API_KEY` | none | key for OpenRouter (the setup can store it instead) |
|
|
387
|
+
| `OPENROUTER_MODEL` | provider's default | model to start with |
|
|
388
|
+
| `AGENT_MAX_ITERATIONS` | 150 | tool-call steps per message |
|
|
389
|
+
| `AGENT_MAX_COST` | 0 (no limit) | cost limit per message, in dollars |
|
|
390
|
+
| `AGENT_ALLOWED_PATHS` | none | folders the file tools may touch |
|
|
391
|
+
| `MCP_SERVERS` | none | external tool servers |
|
|
392
|
+
| `INTENT_MODEL` | none | optional model that picks the tools for each message; unset offers them all |
|
|
393
|
+
| `FLINT_SPEND` | saved choice | economy, normal or generous |
|
|
394
|
+
| `FLINT_UPDATE_CHECK` | 1 | 0 turns off the daily update check |
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Documentation
|
|
399
|
+
|
|
400
|
+
- [docs/guide.md](docs/guide.md): user guide
|
|
401
|
+
- [docs/technical-reference.md](docs/technical-reference.md): modules, tools and settings in detail
|
|
402
|
+
- [docs/providers.md](docs/providers.md): providers and keys
|
|
403
|
+
- [docs/console-spec.md](docs/console-spec.md): the console
|
|
404
|
+
- [docs/stdio-mode.md](docs/stdio-mode.md), [docs/context-swap.md](docs/context-swap.md),
|
|
405
|
+
[docs/spend-modes.md](docs/spend-modes.md), [docs/free-mode.md](docs/free-mode.md),
|
|
406
|
+
[docs/model-check.md](docs/model-check.md), [docs/self-update.md](docs/self-update.md)
|
|
407
|
+
- [FEATURES.md](FEATURES.md): feature list
|
|
408
|
+
- [CHANGELOG.md](CHANGELOG.md): what changed in each version
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Development
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
git clone https://github.com/dklymentiev/flint-agent.git
|
|
416
|
+
cd flint-agent
|
|
417
|
+
npm install
|
|
418
|
+
npm test
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Flint and its tests need Node.js 22.12 or newer. No `.env` and no API key
|
|
422
|
+
are needed: the tests stub the model.
|
|
423
|
+
|
|
424
|
+
Stack: Node.js (ESM), React 19 and Ink 6 for the terminal UI, Zustand for
|
|
425
|
+
state, SQLite for the message queue, tasks and memory index.
|
|
426
|
+
|
|
427
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) before sending a change.
|
|
428
|
+
|
|
429
|
+
If Flint is useful to you, a star on GitHub helps other people find it.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## License
|
|
434
|
+
|
|
435
|
+
[MIT](LICENSE)
|
package/bin/flint.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Flint CLI entry point
|
|
4
|
+
// Delegates to launcher.js (which handles auto-restart on exit code 42).
|
|
5
|
+
// Plain Node, no loader: the source has no JSX (components call
|
|
6
|
+
// createElement). The esbuild loader this used to start with was a dev
|
|
7
|
+
// dependency, so `npm install -g` left `flint` unable to start.
|
|
8
|
+
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const launcher = join(__dirname, "..", "src", "launcher.js");
|
|
15
|
+
|
|
16
|
+
// `flint --version`: the quickest check that the command works after an
|
|
17
|
+
// install, without starting anything.
|
|
18
|
+
if (process.argv.includes("--version") || process.argv.includes("-v")) {
|
|
19
|
+
const { readFileSync } = await import("node:fs");
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
|
|
21
|
+
console.log(`flint ${pkg.version}`);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// The stdio mode runs in this process: no launcher, no splash, no restart.
|
|
26
|
+
// A host may pass files as inherited descriptors (--system-prompt-file
|
|
27
|
+
// /proc/self/fd/N), and a child process does not get
|
|
28
|
+
// them: through bin, launcher and index.js the path named some other
|
|
29
|
+
// descriptor of the grandchild, and reading it hung the start (Linux,
|
|
30
|
+
// 2026-10-02). One process is also the one the host signals.
|
|
31
|
+
const userArgs = process.argv.slice(2);
|
|
32
|
+
const stdioMode = userArgs.includes("--stdio") || userArgs.some((a, i) =>
|
|
33
|
+
(a === "--input-format" || a === "--output-format") && userArgs[i + 1] === "stream-json");
|
|
34
|
+
if (stdioMode) {
|
|
35
|
+
await import(new URL("../src/index.js", import.meta.url));
|
|
36
|
+
} else {
|
|
37
|
+
|
|
38
|
+
const child = spawn(process.execPath, [
|
|
39
|
+
launcher,
|
|
40
|
+
...userArgs,
|
|
41
|
+
], {
|
|
42
|
+
stdio: "inherit",
|
|
43
|
+
cwd: process.cwd(),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
child.on("exit", (code) => process.exit(code ?? 1));
|
|
47
|
+
}
|