nff 0.2.1__tar.gz → 0.2.2__tar.gz

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 (36) hide show
  1. {nff-0.2.1 → nff-0.2.2}/PKG-INFO +1 -1
  2. {nff-0.2.1 → nff-0.2.2}/nff/cli.py +2 -0
  3. nff-0.2.2/nff/commands/clean.py +117 -0
  4. {nff-0.2.1 → nff-0.2.2}/nff/commands/init.py +12 -1
  5. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/PKG-INFO +1 -1
  6. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/SOURCES.txt +1 -0
  7. {nff-0.2.1 → nff-0.2.2}/pyproject.toml +1 -1
  8. {nff-0.2.1 → nff-0.2.2}/LICENSE +0 -0
  9. {nff-0.2.1 → nff-0.2.2}/README.md +0 -0
  10. {nff-0.2.1 → nff-0.2.2}/nff/__init__.py +0 -0
  11. {nff-0.2.1 → nff-0.2.2}/nff/commands/__init__.py +0 -0
  12. {nff-0.2.1 → nff-0.2.2}/nff/commands/doctor.py +0 -0
  13. {nff-0.2.1 → nff-0.2.2}/nff/commands/flash.py +0 -0
  14. {nff-0.2.1 → nff-0.2.2}/nff/commands/monitor.py +0 -0
  15. {nff-0.2.1 → nff-0.2.2}/nff/commands/wokwi.py +0 -0
  16. {nff-0.2.1 → nff-0.2.2}/nff/config.py +0 -0
  17. {nff-0.2.1 → nff-0.2.2}/nff/mcp_server.py +0 -0
  18. {nff-0.2.1 → nff-0.2.2}/nff/tools/__init__.py +0 -0
  19. {nff-0.2.1 → nff-0.2.2}/nff/tools/boards.py +0 -0
  20. {nff-0.2.1 → nff-0.2.2}/nff/tools/installer.py +0 -0
  21. {nff-0.2.1 → nff-0.2.2}/nff/tools/serial.py +0 -0
  22. {nff-0.2.1 → nff-0.2.2}/nff/tools/toolchain.py +0 -0
  23. {nff-0.2.1 → nff-0.2.2}/nff/tools/wokwi.py +0 -0
  24. {nff-0.2.1 → nff-0.2.2}/nff/tools/wokwi_installer.py +0 -0
  25. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/dependency_links.txt +0 -0
  26. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/entry_points.txt +0 -0
  27. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/requires.txt +0 -0
  28. {nff-0.2.1 → nff-0.2.2}/nff.egg-info/top_level.txt +0 -0
  29. {nff-0.2.1 → nff-0.2.2}/setup.cfg +0 -0
  30. {nff-0.2.1 → nff-0.2.2}/tests/test_boards.py +0 -0
  31. {nff-0.2.1 → nff-0.2.2}/tests/test_config.py +0 -0
  32. {nff-0.2.1 → nff-0.2.2}/tests/test_doctor.py +0 -0
  33. {nff-0.2.1 → nff-0.2.2}/tests/test_mcp.py +0 -0
  34. {nff-0.2.1 → nff-0.2.2}/tests/test_serial.py +0 -0
  35. {nff-0.2.1 → nff-0.2.2}/tests/test_toolchain.py +0 -0
  36. {nff-0.2.1 → nff-0.2.2}/tests/test_wokwi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nff
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Claude Code IoT Bridge — connect Claude to hardware via USB
5
5
  Author-email: Gauthier Lechevalier <gauthier.lechevalier26@gmail.com>
6
6
  License-Expression: MIT
@@ -38,12 +38,14 @@ from nff.commands.flash import flash # noqa: E402
38
38
  from nff.commands.monitor import monitor # noqa: E402
39
39
  from nff.commands.doctor import doctor # noqa: E402
40
40
  from nff.commands.wokwi import wokwi # noqa: E402
41
+ from nff.commands.clean import clean # noqa: E402
41
42
 
42
43
  cli.add_command(init)
43
44
  cli.add_command(flash)
44
45
  cli.add_command(monitor)
45
46
  cli.add_command(doctor)
46
47
  cli.add_command(wokwi)
48
+ cli.add_command(clean)
47
49
 
48
50
 
49
51
  @cli.command("install-deps")
@@ -0,0 +1,117 @@
1
+ """nff clean — remove the MCP server registration and optionally the nff config."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import click
12
+ from rich.console import Console
13
+
14
+ from nff import config as cfg_module
15
+
16
+ if sys.platform == "win32" and hasattr(sys.stdout, "reconfigure"):
17
+ sys.stdout.reconfigure(encoding="utf-8")
18
+
19
+ console = Console(legacy_windows=False)
20
+
21
+ _CLAUDE_DESKTOP_CONFIG = Path.home() / ".claude" / "claude_desktop_config.json"
22
+
23
+
24
+ def _remove_from_claude_code() -> bool:
25
+ """Run `claude mcp remove nff`. Returns True on success."""
26
+ if not shutil.which("claude"):
27
+ return False
28
+ try:
29
+ result = subprocess.run(
30
+ ["claude", "mcp", "remove", "nff"],
31
+ capture_output=True,
32
+ text=True,
33
+ timeout=15,
34
+ )
35
+ return result.returncode == 0
36
+ except (OSError, subprocess.TimeoutExpired):
37
+ return False
38
+
39
+
40
+ def _remove_from_claude_desktop_config() -> bool:
41
+ """Remove the nff mcpServers entry from claude_desktop_config.json.
42
+
43
+ Returns True if the entry was present and removed, False if it wasn't there.
44
+ """
45
+ if not _CLAUDE_DESKTOP_CONFIG.exists():
46
+ return False
47
+
48
+ raw = _CLAUDE_DESKTOP_CONFIG.read_text(encoding="utf-8")
49
+ if not raw.strip():
50
+ return False
51
+
52
+ data: dict = json.loads(raw)
53
+ servers: dict = data.get("mcpServers", {})
54
+ if "nff" not in servers:
55
+ return False
56
+
57
+ del servers["nff"]
58
+ if not servers:
59
+ data.pop("mcpServers", None)
60
+
61
+ _CLAUDE_DESKTOP_CONFIG.write_text(json.dumps(data, indent=2), encoding="utf-8")
62
+ return True
63
+
64
+
65
+ @click.command()
66
+ @click.option(
67
+ "--config",
68
+ "remove_config",
69
+ is_flag=True,
70
+ help="Also delete ~/.nff/config.json.",
71
+ )
72
+ def clean(remove_config: bool) -> None:
73
+ """Remove the nff MCP server registration from Claude Code and Claude Desktop."""
74
+ any_removed = False
75
+
76
+ # Claude Code CLI
77
+ if _remove_from_claude_code():
78
+ console.print(
79
+ " [bold green]✓[/bold green] Removed from Claude Code "
80
+ "([bold]claude mcp remove nff[/bold])"
81
+ )
82
+ any_removed = True
83
+ else:
84
+ console.print(
85
+ " [dim]`claude` CLI not found or nff was not registered — skipping.[/dim]"
86
+ )
87
+
88
+ # Claude Desktop JSON config
89
+ try:
90
+ removed = _remove_from_claude_desktop_config()
91
+ if removed:
92
+ console.print(
93
+ f" [bold green]✓[/bold green] Removed nff entry from "
94
+ f"[bold]{_CLAUDE_DESKTOP_CONFIG}[/bold]"
95
+ )
96
+ any_removed = True
97
+ else:
98
+ console.print(
99
+ f" [dim]nff not found in {_CLAUDE_DESKTOP_CONFIG} — nothing to remove.[/dim]"
100
+ )
101
+ except (ValueError, OSError) as exc:
102
+ console.print(f" [yellow]⚠[/yellow] Could not update Claude Desktop config: {exc}")
103
+
104
+ # Optional: nff config file
105
+ if remove_config:
106
+ config_path = cfg_module.CONFIG_PATH
107
+ if config_path.exists():
108
+ config_path.unlink()
109
+ console.print(
110
+ f" [bold green]✓[/bold green] Deleted [bold]{config_path}[/bold]"
111
+ )
112
+ any_removed = True
113
+ else:
114
+ console.print(f" [dim]{config_path} does not exist — nothing to delete.[/dim]")
115
+
116
+ if not any_removed:
117
+ console.print(" Nothing to clean.")
@@ -80,13 +80,24 @@ def _pick_device(devices: list[DetectedDevice]) -> DetectedDevice:
80
80
  def _register_mcp_claude_code() -> bool:
81
81
  """Register nff with Claude Code CLI via `claude mcp add`.
82
82
 
83
+ Uses the absolute path of the running nff executable so Claude Code can
84
+ locate it on Windows where bare-name resolution may fail.
85
+
83
86
  Returns True on success, False if `claude` is not in PATH or the command fails.
84
87
  """
85
88
  if not shutil.which("claude"):
86
89
  return False
90
+
91
+ nff_exe = shutil.which("nff") or sys.executable
92
+ # On Windows prefer the .exe alongside the current interpreter if found
93
+ if sys.platform == "win32":
94
+ candidate = Path(sys.executable).parent / "nff.exe"
95
+ if candidate.exists():
96
+ nff_exe = str(candidate)
97
+
87
98
  try:
88
99
  result = subprocess.run(
89
- ["claude", "mcp", "add", "nff", "nff", "mcp"],
100
+ ["claude", "mcp", "add", "nff", nff_exe, "mcp"],
90
101
  capture_output=True,
91
102
  text=True,
92
103
  timeout=15,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nff
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Claude Code IoT Bridge — connect Claude to hardware via USB
5
5
  Author-email: Gauthier Lechevalier <gauthier.lechevalier26@gmail.com>
6
6
  License-Expression: MIT
@@ -12,6 +12,7 @@ nff.egg-info/entry_points.txt
12
12
  nff.egg-info/requires.txt
13
13
  nff.egg-info/top_level.txt
14
14
  nff/commands/__init__.py
15
+ nff/commands/clean.py
15
16
  nff/commands/doctor.py
16
17
  nff/commands/flash.py
17
18
  nff/commands/init.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nff"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "Claude Code IoT Bridge — connect Claude to hardware via USB"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes