@nanobpm/nano-coder 0.1.0 → 0.2.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.
Files changed (2) hide show
  1. package/README.md +92 -4
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -20,11 +20,12 @@ cargo install nano-coder # or build from source
20
20
  - **Sessions**: Append-only JSONL session logs with resume and input-ID deduplication
21
21
  - **Lifecycle Hooks**: 6 hook events for observing/intercepting agent behavior
22
22
  - **Configuration**: TOML-based config file at `~/.config/nano-coder/config.toml`
23
- - **Commands**: `/help`, `/compact`, `/context`, `/verbosity`, `/settings`, `/tools`, `/exit`
23
+ - **Commands**: `/help`, `/compact`, `/context`, `/verbosity`, `/settings`, `/tools`, `/skills`, `/exit`
24
24
  - **Streaming output**: answers stream in, thinking shows collapsed (Ctrl-O expands it), tool calls show inline
25
25
  - **Status line** pinned to the bottom of the terminal, plus manual and automatic context compaction
26
26
  - **Task plans**: `plan_*` tools keep a plan with notes outside the conversation, so long tasks survive compaction, resume and a change of worker
27
27
  - **Project instructions**: `AGENTS.md` (or `CLAUDE.md`, `.github/copilot-instructions.md`) from the repository is added to the system prompt
28
+ - **Skills**: `SKILL.md` folders from the repository, `~/.agents/skills`, and an spm `ai.lock`, loaded on demand with `load_skill`
28
29
 
29
30
  ## Two Execution Modes
30
31
 
@@ -83,6 +84,8 @@ events c8ctl-nano's transcript producer records into the engine's AgentInstance
83
84
  **Project instructions.** `session/new` and `session/load` results include
84
85
  `_meta.projectInstructions`: the absolute paths of the instruction files that were added to
85
86
  the system prompt for the session's `cwd` (see [Project Instructions](#project-instructions)).
87
+ `_meta.skills` lists the skills found for it, and `_meta.skillWarnings` (when present) explains
88
+ any that could not be loaded (see [Skills](#skills)).
86
89
 
87
90
  **Plans.** Each plan change sends a `plan` update: ACP `entries` (`content`, `priority`,
88
91
  `status`) plus `_meta.plan`, the full plan with ids, notes and dependencies. To continue a job
@@ -133,6 +136,8 @@ src/
133
136
  ├── instructions.rs # AGENTS.md / CLAUDE.md discovery for the system prompt
134
137
  ├── plan.rs # Task plan and the plan_add / plan_update / plan_show tools
135
138
  ├── goal.rs # report_outcome tool (completed / blocked)
139
+ ├── commands.rs # Slash-command table for /help and the as-you-type menu
140
+ ├── skills.rs # SKILL.md discovery, ai.lock sources and the load_skill tool
136
141
  ├── reminders.rs # <system-reminder> notes appended to tool results
137
142
  ├── settings.rs # /settings menu and config-file writer
138
143
  └── config.rs # Configuration file loading and management
@@ -171,6 +176,8 @@ The harness exposes 6 lifecycle hook events:
171
176
  - `plan_add`, `plan_update`, `plan_show` - The agent's task plan (see [Task Plans](#task-plans)).
172
177
  - `report_outcome` - Report the task `completed` or `blocked`, with a `summary`; ends the turn
173
178
  (see [Outcomes](#outcomes)).
179
+ - `load_skill` - Return a skill's instructions and list its other files; `name`. Offered only
180
+ when skills were found (see [Skills](#skills)).
174
181
 
175
182
  Any other tool's result longer than 40,000 characters is cut the same way as bash output,
176
183
  with the whole result saved under the temp directory (`nano-coder-<pid>/tool-<id>-<name>.txt`)
@@ -182,6 +189,10 @@ workspace.
182
189
 
183
190
  ## Commands
184
191
 
192
+ Typing `/` at the prompt lists the commands under it, and each further character narrows the
193
+ list. Tab completes the command, or the part all matches share. Esc hides the list. The
194
+ list is built from the same table as `/help` (`src/commands.rs`).
195
+
185
196
  - `/help` - Show available commands
186
197
  - `/compact [focus]` - Summarize older messages with the current model, keeping the latest
187
198
  message. Optional text tells the summary what to focus on. Esc Esc or Ctrl-C cancels
@@ -199,6 +210,7 @@ workspace.
199
210
  (`--config` or `~/.config/nano-coder/config.toml`), keeping comments and
200
211
  other settings. Leaving with unsaved changes asks whether to save
201
212
  - `/tools` - List registered tools
213
+ - `/skills` - List the skills the agent can load, where each lives, and any loading warnings
202
214
  - `/plan` - Show the agent's task plan with all notes
203
215
  - `/model [provider/model]` - Show or switch the model (conversation is kept)
204
216
  - `/providers` - List providers, endpoints and whether their API key is available
@@ -242,11 +254,20 @@ auto_compact = true # summarize automatically when the conte
242
254
  auto_compact_threshold = 0.8 # fraction of the context window
243
255
  # context_window = 128000 # override the window (providers can set it too)
244
256
  verbosity = "normal" # quiet | normal | verbose | debug (or --verbosity)
257
+ timestamps = true # prefix CLI messages with the local time (HH:MM:SS)
245
258
  project_instructions = true # load AGENTS.md etc. (see Project Instructions)
246
259
  project_instruction_files = ["AGENTS.md", "CLAUDE.md", ".github/copilot-instructions.md"]
247
260
  plan_tools = true # offer the plan_* tools (see Task Plans)
248
261
  outcome_tool = true # offer report_outcome (see Outcomes)
249
262
  reminders = true # append <system-reminder> notes to tool results
263
+
264
+ [skills] # see Skills
265
+ enabled = true
266
+ dirs = [".agents/skills", ".github/skills", ".claude/skills"] # relative to the git root
267
+ user_dirs = ["~/.agents/skills"]
268
+ ai_lock = true # load skills pinned in ai.lock
269
+ fetch = true # fetch ai.lock commits missing from the spm store
270
+ allowed_hosts = ["github.com"] # hosts ai.lock entries may be fetched from ("*" = any)
250
271
  ```
251
272
 
252
273
  The default model is `gpt-4o-mini` on the `mock` provider, so the harness still works offline.
@@ -268,8 +289,10 @@ Built-in presets:
268
289
  | `groq` | openai | `https://api.groq.com/openai/v1` | `GROQ_API_KEY` |
269
290
  | `together` | openai | `https://api.together.xyz/v1` | `TOGETHER_API_KEY` |
270
291
  | `deepseek` | openai | `https://api.deepseek.com/v1` | `DEEPSEEK_API_KEY` |
292
+ | `kimi` | openai | `https://api.moonshot.ai/v1` | `MOONSHOT_API_KEY` |
271
293
  | `mistral` | openai | `https://api.mistral.ai/v1` | `MISTRAL_API_KEY` |
272
294
  | `gemini` | openai | `https://generativelanguage.googleapis.com/v1beta/openai` | `GEMINI_API_KEY` |
295
+ | `qwen` | openai | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `DASHSCOPE_API_KEY` |
273
296
  | `ollama` | openai | `http://localhost:11434/v1` | — |
274
297
  | `llamacpp` | openai | `http://localhost:8080/v1` | — |
275
298
  | `github-copilot` | github-copilot | from session token | `GITHUB_COPILOT_OAUTH_TOKEN` or `--login` (unofficial, see below) |
@@ -307,7 +330,19 @@ timeout_secs = 300
307
330
  max_retries = 3
308
331
  ```
309
332
 
310
- Other per-provider fields: `max_tokens_param` (`max_tokens`, or `max_completion_tokens`
333
+ `qwen` is Qwen Cloud (Alibaba Cloud Model Studio), e.g. `--model qwen/qwen3.8-max`. The
334
+ preset uses the Singapore endpoint. API keys are bound to a region, so for another region
335
+ or your workspace domain override `base_url`, e.g.
336
+ `https://dashscope-us.aliyuncs.com/compatible-mode/v1` or
337
+ `https://<WorkspaceId>.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1`.
338
+
339
+ `kimi` is the Kimi API from platform.kimi.ai, e.g. `--model kimi/kimi-k3` or
340
+ `kimi/kimi-k2.7-code`. The preset drops `temperature` (K3 fixes it) and sets
341
+ `replay_reasoning = true`, which sends each assistant message's `reasoning_content` back
342
+ as thinking models like K3 require. Set `extra_body = { reasoning_effort = "low" }` to
343
+ make K3 think less.
344
+
345
+ Other per-provider fields: `replay_reasoning`, `max_tokens_param` (`max_tokens`, or `max_completion_tokens`
311
346
  which is the `openai` default), `retry_initial_backoff_ms`, `retry_max_backoff_ms` and
312
347
  `retryable_statuses`.
313
348
 
@@ -384,6 +419,10 @@ Streaming uses server-sent events. Set `stream = false` on a provider whose endp
384
419
  support it. ACP mode doesn't stream text, but sends each response's reasoning as an
385
420
  `agent_thought_chunk` update.
386
421
 
422
+ Every message (your prompt, answers, tool calls and results, thinking, notes) starts with
423
+ the local time as `HH:MM:SS`. The prompt's time is rewritten when you press Enter, so it
424
+ shows when the message was sent. Turn this off with `timestamps = false`.
425
+
387
426
  ## Status Line and Compaction
388
427
 
389
428
  In an interactive terminal the bottom row shows the provider/model, context usage
@@ -393,8 +432,22 @@ count, and what the agent is doing. It uses a terminal scroll region, follows re
393
432
  off when stdin/stdout isn't a TTY or `AGENTIC_NO_STATUS` is set.
394
433
 
395
434
  The context window comes from, in order: `context_window` in the config, `context_window`
396
- on the provider, a built-in table of known models, then 128k. If a provider rejects a
397
- request as too long, the harness takes the limit from the error, compacts, and retries once.
435
+ on the provider, the window the endpoint reports, a built-in table of known models, then
436
+ 128k. `/context` shows which one applied. If a provider rejects a request as too long, the
437
+ harness takes the limit from the error, compacts, and retries once.
438
+
439
+ The endpoint is asked at startup and on `/model` (at most 5 seconds; skipped when config
440
+ sets the window). The window a server has *loaded* is preferred over the model's maximum:
441
+
442
+ | Server | Source |
443
+ |---|---|
444
+ | vLLM | `/v1/models` `max_model_len` |
445
+ | DwarfStar ds4, OpenRouter, Together, Kimi | `/models` `context_length` |
446
+ | Groq / Mistral | `/models` `context_window` / `max_context_length` |
447
+ | llama.cpp | `/props` `n_ctx` (per slot) |
448
+ | LM Studio | `/api/v0/models` `loaded_context_length` |
449
+ | Ollama | `/api/ps` for a loaded model, else `num_ctx`; never the model maximum, since Ollama runs with a smaller default |
450
+ | GitHub Copilot | `/models` `max_prompt_tokens` |
398
451
 
399
452
  Compaction asks the current model to summarize older messages, keeping the recent tail
400
453
  (up to 20k tokens, never starting at a tool result). Auto-compaction runs before a model
@@ -424,6 +477,39 @@ Instructions are read again when a session is resumed, so edits to `AGENTS.md` t
424
477
  `/context` lists the loaded files. To turn loading off, set `project_instructions = false`,
425
478
  or set `AGENTIC_NO_PROJECT_INSTRUCTIONS`.
426
479
 
480
+ ## Skills
481
+
482
+ A skill is a folder with a `SKILL.md`: YAML front matter with a `name` and a `description`,
483
+ then instructions, plus any scripts or reference files it needs. Only the name and description
484
+ of each skill go into the system prompt, under a "Skills" heading (8 KiB at most). When a task
485
+ matches one, the model calls `load_skill`, which returns the instructions (32 KiB at most),
486
+ the skill's directory, and a list of its other files for `read_file`.
487
+
488
+ Skills are found in this order, and the first skill with a given name wins:
489
+
490
+ 1. **Repository**: `.agents/skills`, `.github/skills` and `.claude/skills` under the git root,
491
+ at any depth up to four folders (`skills/<group>/<skill>/SKILL.md` works).
492
+ 2. **`ai.lock`**: skills pinned by [spm](https://github.com/camunda/spm-cli). Each locked
493
+ skill is loaded, and so is each skill bundled in a locked plugin (its
494
+ `.claude-plugin/plugin.json` `skills` folder, default `skills/`). Hooks, commands and MCP
495
+ servers in plugins are not loaded.
496
+ 3. **User**: `~/.agents/skills`.
497
+
498
+ nano-coder reads `ai.lock` itself and never runs `spm install`, which edits the workspace
499
+ (`.gitignore`, vendor folders). Changes like that would end up in commits and PRs. Each
500
+ pinned commit is read from spm's store (`$SPM_HOME/store`, default `~/.spm/store`) if it is
501
+ there. Otherwise it is fetched once into the nano-coder cache (`<cache dir>/nano-coder/skills`).
502
+ `ai.lock` is committed to the repository, so its entries are checked the way spm checks them:
503
+ a full 40-character commit, a store key that matches the URL and commit, and paths that stay
504
+ inside the checkout. Fetches are limited to `skills.allowed_hosts` (`"file"` allows
505
+ `file://`). With `fetch = false`, only commits already in the spm store or the cache are used.
506
+ An `ai.json` without an `ai.lock` is skipped with a warning, because unpinned references are
507
+ never resolved.
508
+
509
+ Skills are found again when a session starts or is resumed. Problems are listed at startup
510
+ and by `/skills` (and returned as `_meta.skillWarnings` over ACP); they never stop a session.
511
+ To turn skills off, set `skills.enabled = false` or set `NANO_CODER_NO_SKILLS`.
512
+
427
513
  ## Task Plans
428
514
 
429
515
  The `plan_*` tools give the agent a plan that lives outside the conversation. This helps most
@@ -479,6 +565,8 @@ When `persist_sessions` is on, each conversation is written to `<session_dir>/<i
479
565
  The file is an append-only log whose first record is a versioned header, followed by
480
566
  `input`, `message`, `turn_end` and `replace` (compaction / system-prompt reset) records.
481
567
  Resume a session with `--resume <id>` or ACP `session/load`.
568
+ Record times and each message's `timestamp` are RFC 3339 with the local UTC offset
569
+ (for example `2026-09-24T13:02:12.44+12:00`). Older logs with UTC times still load.
482
570
 
483
571
  - An unsupported format version is an explicit error on resume.
484
572
  - Only records ending in a newline count as committed. A half-written last line from a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-coder",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A 6MB coding agent. Run a fleet on your laptop.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -31,9 +31,9 @@
31
31
  "node": ">=18"
32
32
  },
33
33
  "optionalDependencies": {
34
- "@nanobpm/nano-coder-darwin-arm64": "0.1.0",
35
- "@nanobpm/nano-coder-darwin-x64": "0.1.0",
36
- "@nanobpm/nano-coder-linux-arm64": "0.1.0",
37
- "@nanobpm/nano-coder-linux-x64": "0.1.0"
34
+ "@nanobpm/nano-coder-darwin-arm64": "0.2.0",
35
+ "@nanobpm/nano-coder-darwin-x64": "0.2.0",
36
+ "@nanobpm/nano-coder-linux-arm64": "0.2.0",
37
+ "@nanobpm/nano-coder-linux-x64": "0.2.0"
38
38
  }
39
39
  }