Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9fdd94c
refactor(setup nu): replace action flags with subcommands + shared co…
tonythethompson Aug 1, 2026
633c50c
fix: 3 findings — Prevent PATH subcommand from deleting active managed N
qodo-code-review[bot] Aug 1, 2026
fb0ff23
fix: address PR #66 review feedback
tonythethompson Aug 1, 2026
438d80b
fix: clarify PATH messaging in Nu setup hints
tonythethompson Aug 1, 2026
7e726a2
Add reserved `numan use` CLI stub
tonythethompson Aug 1, 2026
7951797
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] Aug 1, 2026
8062a11
feat: implement numan use for side-by-side Nu version management
tonythethompson Aug 1, 2026
213e874
fix: 5 findings — Validate and normalize Nu versions; Propagate legacy m
qodo-code-review[bot] Aug 1, 2026
b8f4233
fix: address PR review — validate before delete, fix help text, fix c…
tonythethompson Aug 1, 2026
62b8656
chore: remove temp files
tonythethompson Aug 1, 2026
2591036
Update src/cmd/snapshot.rs
tonythethompson Aug 2, 2026
d9b8e0f
fix: PR 67 review - bootstrap yes flag, version check, mutation lock
tonythethompson Aug 2, 2026
0429557
Merge origin/master into feature/numan-use - resolve conflicts: take …
tonythethompson Aug 2, 2026
e245232
Update .gitignore
tonythethompson Aug 2, 2026
641bd24
wip(numan-use): integrate use + migration pieces (split pending)
tonythethompson Aug 2, 2026
3a38bbf
feat(numan-use): strip migration pieces for pr-migrate split
tonythethompson Aug 2, 2026
6894382
fix(cmd): address PR 67 review findings (validate versions, drop --us…
tonythethompson Aug 2, 2026
25f57b1
fix(bootstrap): install_from_archive writes to versioned layout
tonythethompson Aug 2, 2026
7c8cc58
fix(numan-use): address remaining 7 PR 67 review threads
tonythethompson Aug 2, 2026
ec949e9
fix(numan-use): confirm.rs ConfirmPolicy + hints.rs shell_quote + set…
tonythethompson Aug 2, 2026
e15e5d3
ci(roadmap): detect roadmap drift before it ships
tonythethompson Aug 2, 2026
d5432d9
docs(roadmap): audit each Post-1.0 claim against shipped code
tonythethompson Aug 2, 2026
99aa695
ci(roadmap): mirror drift check into numan-plugins and numan-registry
tonythethompson Aug 2, 2026
dcd6ad6
Merge branch 'master' into feature/numan-use
tonythethompson Aug 2, 2026
48c3941
fix(version_manager): make is_version_installed consult off-tree acti…
devin-ai-integration[bot] Aug 2, 2026
5022ce2
fix: resolve MSRV compile, format, and test failures for numan use
devin-ai-integration[bot] Aug 2, 2026
ad6ce88
Apply 3 edits across 1 file
devin-ai-integration[bot] Aug 2, 2026
8acbfeb
Apply 1 edit across 1 file
devin-ai-integration[bot] Aug 2, 2026
5d200a1
fix: don't take mutation lock/snapshot for read-only `numan use list`
devin-ai-integration[bot] Aug 2, 2026
6f842c4
fix: rustfmt and update injected-installer test for versioned layout
devin-ai-integration[bot] Aug 2, 2026
193fbb1
test: assert `numan use list` takes no snapshot while switch does
devin-ai-integration[bot] Aug 2, 2026
aedf804
Wire destructive-op TTY guard and clear active-version marker on mana…
devin-ai-integration[bot] Aug 2, 2026
23c0e31
Apply 1 edit across 1 file
devin-ai-integration[bot] Aug 2, 2026
993acea
fix(mirror-dry-run): capture drift-check exit code under set -e
devin-ai-integration[bot] Aug 2, 2026
4f3f478
chore: remove one-off apply_install_from_archive_fix.py (already appl…
devin-ai-integration[bot] Aug 2, 2026
1331ecf
fix: allow injected confirm seam to bypass TTY guard in tests
devin-ai-integration[bot] Aug 2, 2026
8245978
Merge branch 'master' into feature/numan-use
tonythethompson Aug 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ src/
gc.rs — `numan gc [--dry-run]`: delete orphaned payload directories (Phase 5)
nupm.rs — `numan nupm status|inspect|import|diff`: nupm discovery + import + drift (Phase 6.1–6.3)
completions.rs — `numan completions <shell>`: bash/fish/zsh/powershell/nushell scripts (Phase 7.3)
setup.rs — `numan setup nu [--version]|loader`: Nushell bootstrap (pinned or latest) + nushell-loader install
setup.rs — `numan setup nu [VERSION]|remove|path|use <path>` + `setup loader`: Nushell bootstrap + nushell-loader install
try_cmd.rs — `numan try [--yes] [--no-activate]`: curated starter install + activate for current Nu
nu_pin_offer.rs — Shared TTY offer to `setup nu --version` + `init --refresh` on Nu mismatch
use_cmd.rs — `numan use <version>`: reserved stub for side-by-side Nu version management (post-1.0)
Comment thread
tonythethompson marked this conversation as resolved.
Outdated
nu_pin_offer.rs — Shared TTY offer to `setup nu <version>` + `init --refresh` on Nu mismatch
install/
download.rs — HTTP download with progress
extract.rs — tar/zip/xz archive extraction
Expand Down Expand Up @@ -229,8 +230,8 @@ Standard build/test/lint/run commands live in "Build & Test" above and in the RE

## Learned Workspace Facts
- Plugin ABI is Nu-minor-scoped: mixed plugin ABIs cannot run inside one Nu process; side-by-side Nu profiles would be a separate future product shape, not a near-term substitute for compat UX.
- PATH Nu can be newer than official-registry Windows plugin Nu constraints, so `search` can look fine while `install` fails; use compat-filtered search / `numan try` / `setup nu --version`.
- `numan setup nu --version <x.y.z>` pins a managed Nu release; default without `--version` still installs latest.
- PATH Nu can be newer than official-registry Windows plugin Nu constraints, so `search` can look fine while `install` fails; use compat-filtered search / `numan try` / `setup nu <version>`.
- `numan setup nu <x.y.z>` pins a managed Nu release; bare `numan setup nu` installs latest. Subcommands: `remove`, `path`, `use <path>`.
- Numan product spans three repos (`numan`, `numan-registry`, `numan-plugins`); trust is cross-cutting (client verifies, registry signs); there is no separate `numan-registry.trust` product repo.
- Near-term adoption bottleneck is thin catalog depth; release handoff is numan-plugins → numan-registry → numan client.
- `numan registry sync` only refreshes the local catalog; it does not install packages (`list` stays empty until `install`).
Expand All @@ -239,4 +240,4 @@ Standard build/test/lint/run commands live in "Build & Test" above and in the RE
- Prefers streamlining Nu-compat onboarding as honest search/install UX, a one-shot starter, and an offer-based managed Nu pin (never silent auto-switch of Nu).
- Prefers the command name `numan try` for the prove-it-works starter (not `setup demo` / `setup starter`).
- Product north star for Numan: make the Nushell package ecosystem more inviting for less experienced users.
- PATH Nu can be newer than official-registry Windows plugin Nu constraints, so `search` can look fine while `install` fails; use compat-filtered search / `numan try` / `setup nu --version`.
- PATH Nu can be newer than official-registry Windows plugin Nu constraints, so `search` can look fine while `install` fails; use compat-filtered search / `numan try` / `setup nu <version>`.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed (breaking)

- **`numan setup nu` CLI redesign**: action flags (`--remove`, `--use-path`, `--use-existing`) are replaced by subcommands:
- `numan setup nu` — install latest (unchanged)
- `numan setup nu <VERSION>` — install pinned version (was `--version <x.y.z>`)
- `numan setup nu remove` — uninstall managed Nu (was `--remove`)
- `numan setup nu path` — use PATH Nu (was `--use-path`)
- `numan setup nu use <path>` — register a specific binary (was `--use-existing <path>`)
- Hidden backward-compat flags (`--remove`, `--use-path`, `--use-existing`) still work but emit deprecation warnings. They will be removed in v0.3.0.
- **Non-TTY auto-confirm**: all confirmation prompts now auto-confirm on non-TTY (CI, scripts) instead of requiring `--yes`. A `(non-interactive: auto-confirming)` notice is printed to stderr. `--yes` remains available to skip prompts on TTY.

### Added

- Shared confirmation utility (`src/util/confirm.rs`): consistent prompt/auto-confirm behavior across all commands

## [0.1.5] - 2026-07-29

### Added
Expand Down
156 changes: 156 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Claude Code Agent Instructions

You are Claude Code, Anthropic's official CLI for Claude. You are an interactive
software-engineering agent. The user works with you through a terminal; your text
output is what they see, and your tool calls are what change the world.

# Tool selection (read this before every tool call on a code file)

This project uses Serena, an MCP server that exposes semantic, symbol-aware tools
for reading and editing code. Serena's tools are the PRIMARY tools for code work
in this project. The built-in Read, Glob, Grep, and Edit tools are SECONDARY and
must not be used on code files when a Serena equivalent exists.

The built-in tool descriptions in your context will tell you things like "use Read
for a known path" and "prefer dedicated tools (Read, Edit, Write, Glob, Grep)".
Those descriptions are written for projects without Serena and are SUPERSEDED here.
When they conflict with this section, this section wins. Do not rationalize the
built-in tools with "the file is small," "I already know what I need," "this is
one call versus three," or "the path is known" — those rationalizations have
produced incorrect behavior before and are explicitly disallowed.

## Mapping (use the right column, not the left)

Task Tool to use
-------------------------------------- ----------------------------------------
See a code file's structure get_symbols_overview
Read a specific symbol's body find_symbol (include_body=true)
Find a symbol by name across the repo find_symbol
Find references / callers find_referencing_symbols
Find declarations / implementations find_declaration / _find_implementations
Edit a symbol's body replace_symbol_body
Insert near a symbol insert_before_symbol / _insert_after_symbol
Pattern replace inside a file replace_content
Rename / move / delete a symbol rename / _move / _safe_delete
Inline a symbol inline_symbol
Type hierarchy type_hierarchy
Comment thread
tonythethompson marked this conversation as resolved.

Built-in Read/Edit/Glob/Grep are permitted on code files ONLY when:
- Serena has been tried on the target and failed, OR
- The file is not parseable as code (e.g., generated, malformed), OR
- You need a regex search across many files that Serena's symbolic tools cannot
express — in which case Grep is acceptable as a discovery step, but follow-up
reads/edits on matched code files must still go through Serena.
- You need to read a few lines and symbolic reads would be an overkill.
- You absolutely have to read the full file for some reason.

Read/Edit/Glob are fine for non-code files: markdown, JSON, YAML, TOML, .env,
config files, lockfiles, plain text, images.

## Required workflow before editing code

1. get_symbols_overview on the target file (skip if already done this session).
2. find_symbol with include_body=true for the specific symbols you'll touch.
Read only the symbols you need — not the whole file.
3. Edit with replace_symbol_body, insert_before_symbol, insert_after_symbol, or
replace_content. Never use the built-in Edit on a code file when one of these
fits.

## Self-check

Before every Read, Glob, Grep, or Edit call: "Does this target a code file, and
does the mapping above name a Serena tool for this task?" If yes, switch. Do this
check every time — not just once per session.

# Doing tasks

The user will ask you to fix bugs, add features, refactor, explain code, and
similar. Approach each task with these defaults:

- Understand before changing. Use the symbolic tools to build a precise picture of
what's there, then make the smallest change that satisfies the request.
- Don't add scope. No surrounding cleanup on a bug fix, no abstractions for
hypothetical future needs, no error handling for cases that can't happen, no
feature flags or backwards-compat shims unless asked. Three similar lines beats
a premature abstraction.
- Don't write comments unless the WHY is non-obvious — a hidden constraint, a
workaround, a subtle invariant. Don't narrate WHAT the code does; well-named
identifiers handle that. Don't reference the current task or PR in comments.
- Prefer editing existing files to creating new ones. Never create *.md or README
files unless the user explicitly asks.
- For exploratory questions ("what could we do about X?"), reply in 2–3 sentences
with a recommendation and the main tradeoff. Don't implement until the user
agrees.
- For UI/frontend changes you can't test in a browser, say so explicitly rather
than claiming success.
- Watch for security issues (injection, XSS, SQL injection, path traversal, secret
leaks). Fix them when you spot them.

# Executing actions with care

Local, reversible actions (editing files, running tests, reading state) are free
to take. Pause and confirm before:

- Destructive ops: deleting files/branches, dropping tables, killing processes,
rm -rf, overwriting uncommitted changes, git reset --hard, force-push.
- Hard-to-reverse ops: amending published commits, removing dependencies,
modifying CI/CD.
- Externally visible actions: pushing, opening/closing/commenting on PRs or
issues, sending messages, posting to third-party services.
- Uploading content to third-party tools (renderers, pastebins) — assume it's
public and may be cached.

If you hit an obstacle, find the root cause. Don't bypass it with --no-verify,
--force, or by deleting the thing in your way. If you find unfamiliar files,
branches, or config, investigate before deleting — it may be the user's
in-progress work.

A user approving an action once does not approve it forever. Match the scope of
your action to what was actually requested.

# Git and commits

- Only commit when the user asks. Never proactively.
- Never update git config. Never skip hooks (--no-verify, --no-gpg-sign) unless
the user explicitly asks.
- Prefer new commits over --amend. If a pre-commit hook fails, the commit didn't
happen — fix the issue, re-stage, and create a NEW commit (not --amend, which
would modify the previous commit).
- Stage files by name, not `git add -A` or `git add .` — those can sweep in
secrets or large binaries.
- Don't commit files that look like secrets (.env, credentials.json, *.pem). If
the user explicitly asks, warn first.
- For commit messages, use a HEREDOC to preserve formatting. End the trailer with:
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread
tonythethompson marked this conversation as resolved.
Outdated
- Don't push unless asked. Never force-push to main/master; warn if asked.
- For PRs, use `gh` via Bash. Look at the full diff against the base branch (not
just the latest commit) before drafting title/body.

# Tone and output

- Your tool calls aren't visible to the user — only your text is. Before your
first tool call, say in one sentence what you're about to do. While working,
give short updates at key moments: a finding, a direction change, a blocker.
Brief is good; silent is not.
- Don't narrate internal deliberation. State results and decisions; skip the
thinking-aloud.
- End-of-turn summary: one or two sentences max. What changed, what's next.
Nothing else.
- Match response shape to the task: a simple question gets a direct answer, not
headers and sections.
- No emojis unless the user asks.
- Use Github-flavored markdown. Reference code locations as `path:line` so the
user can jump.

# Parallel tool calls

When tool calls don't depend on each other, issue them in a single response.
When they do depend on each other, issue them sequentially with the dependent
values resolved. Don't use placeholders or guess.

# Asking for help vs. acting

When a request is ambiguous in a way that materially changes the work, ask one
focused question. When it's only ambiguous in ways that don't change the work,
pick the reasonable interpretation and proceed — and say which interpretation
you picked.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ numan install vyadh/nutest
numan activate vyadh/nutest --yes
```

Install is **inert** — nothing is registered with Nu until you run `numan activate` (or `numan try`, which activates after install). If a package needs a different Nu minor, Numan explains the mismatch and can offer `numan setup nu --version <x.y.z>` (activations are per-Nu; re-activate after switching). When no compatible starter exists, `numan try` suggests installing a matching managed Nu version or searching for another package with `numan search`.
Install is **inert** — nothing is registered with Nu until you run `numan activate` (or `numan try`, which activates after install). If a package needs a different Nu minor, Numan explains the mismatch and can offer `numan setup nu <x.y.z>` (activations are per-Nu; re-activate after switching). When no compatible starter exists, `numan try` suggests installing a matching managed Nu version or searching for another package with `numan search`.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

After Nu upgrades, refresh cached paths and activation identity:

Expand Down Expand Up @@ -323,7 +323,10 @@ Global flag: `--root <path>` — override the Numan root directory (all commands
| `numan snapshot delete <id> [--yes]` | Delete a snapshot |
| `numan snapshot rollback <id> [--yes]` | Restore exactly a stored snapshot |
| `numan registry list\|sync\|add\|remove\|packages` | Registry management |
| `numan setup nu [--version <x.y.z>]` | Download and install official Nushell under Numan root (optionally pinned) |
| `numan setup nu [VERSION]` | Download and install official Nushell under Numan root (optionally pinned) |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| `numan setup nu remove` | Remove the managed Nushell install and fall back to PATH Nu |
| `numan setup nu path` | Use the Nushell already on PATH (removes managed install) |
| `numan setup nu use <path>` | Register a specific existing Nushell binary |
Comment thread
tonythethompson marked this conversation as resolved.
| `numan nupm status` | Summarize nupm home and import eligibility |
| `numan nupm inspect [--all] [path]` | Classify nupm packages at a path |
| `numan nupm import [--as owner/name] [path]` | One-way import into Numan |
Expand All @@ -347,6 +350,7 @@ Global flag: `--root <path>` — override the Numan root directory (all commands
| `nupm inspect` | `--all` scan home; `--nupm-home <path>`; `--exit-on-ineligible` fail on ineligible |
| `nupm import` | `--as owner/name` (single import); `--manifest <file>` (batch); `--nupm-home <path>`; `--yes` skip consent |
| `doctor` | `--fix` apply safe repairs; `--yes` skip confirm tier; `--json` machine output; `--nupm-home <path>` |
| `setup nu` | `--force` re-download; `--skip-path` don't update PATH; `--yes` skip prompt |

Run `numan <command> --help` for full flag documentation.

Expand Down
2 changes: 2 additions & 0 deletions assets/nushell-loader/loader.nu
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Generated and managed by Numan. Do not edit.
# Numan autoload schema: 1
# Vendored from https://github.com/aidnem/nushell-loader (MIT, Copyright (c) 2026 aidnem)
# Installed by `numan setup loader`. Re-run with --force to update.

Expand Down
8 changes: 4 additions & 4 deletions docs/numan-doctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ Repair steps run in this **order** (each step re-validates only what it changed)
| **auto** | Never | `layout.*` (missing dirs), `nu_paths.missing` | `create_dir_all` for layout; `numan init` |
| **auto** | Never | `registry.index_missing` | `numan registry sync` |
| **auto** | Never | `registry.none` (production trust root only) | Add official registry via same path as `numan init` |
| **confirm** | Unless `--yes` / non-TTY | `nu.binary.missing_on_path` | `numan setup nu --yes` (downloads managed Nushell) |
| **confirm** | Unless `--yes` / non-TTY | `nu.binary.found_off_path` | `numan setup nu --use-existing <path> --yes` (adds existing install to PATH) |
| **confirm** | Unless `--yes` / non-TTY | `nu.binary.missing_on_path` | `numan setup nu` (downloads managed Nushell) |
| **confirm** | Unless `--yes` / non-TTY | `nu.binary.found_off_path` | `numan setup nu use <path>` (adds existing install to PATH) |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| **confirm** | Unless `--yes` / non-TTY | `nu_paths.drift`, `nu_paths.vendor_drift` | `numan init --refresh` |
| **confirm** | Unless `--yes` / non-TTY | `journal.plugin_pending`, `journal.autoload_pending`, `journal.plugin_stale`, `journal.autoload_stale`, `activation.plugin_stale`, `activation.module_stale`, `autoload.projection`, `autoload.managed_missing` | `numan activate` (empty package list — reconciles journals and re-activates stale entries; same entry point as normal activate recovery) |
| **confirm** | Unless `--yes` / non-TTY | `journal.plugin_deactivate_pending` | `numan deactivate <journal package ids>` (reconciles pending-plugin-deactivate journal only; not a full-root deactivate) |
Expand Down Expand Up @@ -115,7 +115,7 @@ Checks run in order below. Implementation should call existing validators (`NuPa
| ID | Severity | Condition |
|----|----------|-----------|
| `nu.binary.missing_on_path` | `error` | Nu not on PATH and not under `$NUMAN_ROOT/tools/nushell/` → fix: `numan setup nu` |
| `nu.binary.found_off_path` | `warn` | Nu exists in a known install root (e.g. `~/.cargo/bin`, `%LOCALAPPDATA%\Programs\nushell`) but not on PATH → fix: `numan setup nu --use-existing <path> --yes` |
| `nu.binary.found_off_path` | `warn` | Nu exists in a known install root (e.g. `~/.cargo/bin`, `%LOCALAPPDATA%\Programs\nushell`) but not on PATH → fix: `numan setup nu use <path>` |
| `nu.path.version` | `info` | PATH-only Nu version (`PATH Nu: 0.114.1`), `PATH Nu: not found`, or `PATH Nu: found at '<path>' but version probe failed (<error>)` when the binary exists but `--version` fails. Does not treat managed Nu as PATH. Report-only (no `--fix`). |
| `nu.managed.version` | `info` | Managed binary under `$NUMAN_ROOT/tools/nushell/` with version, `Managed Nu: not installed`, or `Managed Nu: present at '<path>' but version probe failed (<error>)` when the binary exists but `--version` fails. Report-only (no `--fix`). |
| `nu_paths.missing` | `error` | `paths.json` absent → fix: `numan init` |
Expand Down Expand Up @@ -263,7 +263,7 @@ pub fn execute_with_options(args: &DoctorArgs, root: &Path, options: DoctorOptio
|---------|------|
| `numan init` / `init --refresh` | **Repair** Nu path drift (`--fix` delegates here) |
| `numan setup nu` | **Repair** missing Nushell (`nu.binary.missing_on_path`; `--fix` downloads managed binary) |
| `numan setup nu --use-existing` | **Repair** off-PATH Nushell (`nu.binary.found_off_path`; `--fix` adds parent dir to user PATH) |
| `numan setup nu use <path>` | **Repair** off-PATH Nushell (`nu.binary.found_off_path`; `--fix` adds parent dir to user PATH) |
| `numan activate` | **Repair** activation + journal reconciliation (`--fix` delegates here) |
| `numan registry sync` | **Repair** missing index cache (`--fix` auto tier) |
| `numan activate --check` | Deep **module** check only; no repair |
Expand Down
2 changes: 1 addition & 1 deletion docs/plans/2026-07-29-remaining-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**Status date:** 2026-07-29

**Superseded:** Use the consolidated multi-repo plan
[`2026-07-30-consolidated-multi-repo-roadmap.md`](2026-07-30-consolidated-multi-repo-roadmap.md).
[`consolidated-multi-repo-roadmap.md`](consolidated-multi-repo-roadmap.md).
This file is retained as the prior client draft for history.

---
Expand Down
Loading