ccmd 2.0.3__tar.gz → 2.0.5__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 (54) hide show
  1. {ccmd-2.0.3/ccmd.egg-info → ccmd-2.0.5}/PKG-INFO +1 -1
  2. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/__init__.py +1 -1
  3. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/browser.py +14 -14
  4. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/hub.py +32 -29
  5. {ccmd-2.0.3 → ccmd-2.0.5/ccmd.egg-info}/PKG-INFO +1 -1
  6. {ccmd-2.0.3 → ccmd-2.0.5}/pyproject.toml +1 -1
  7. {ccmd-2.0.3 → ccmd-2.0.5}/LICENSE +0 -0
  8. {ccmd-2.0.3 → ccmd-2.0.5}/MANIFEST.in +0 -0
  9. {ccmd-2.0.3 → ccmd-2.0.5}/README.md +0 -0
  10. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/__main__.py +0 -0
  11. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/cli.py +0 -0
  12. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/config/__init__.py +0 -0
  13. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/config/paths.py +0 -0
  14. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/config/schema.py +0 -0
  15. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/__init__.py +0 -0
  16. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/__init__.py +0 -0
  17. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/aider.py +0 -0
  18. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/base.py +0 -0
  19. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/chatgpt.py +0 -0
  20. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/claude.py +0 -0
  21. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/codex.py +0 -0
  22. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/cursor.py +0 -0
  23. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/goose.py +0 -0
  24. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/agents/grok.py +0 -0
  25. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/fs.py +0 -0
  26. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/launcher.py +0 -0
  27. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/migrate.py +0 -0
  28. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/profiles.py +0 -0
  29. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/projects.py +0 -0
  30. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/scan.py +0 -0
  31. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/sessions.py +0 -0
  32. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/core/ssh.py +0 -0
  33. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/mcp/__init__.py +0 -0
  34. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/mcp/server.py +0 -0
  35. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/__init__.py +0 -0
  36. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/app.py +0 -0
  37. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/ascii.py +0 -0
  38. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/__init__.py +0 -0
  39. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/agents.py +0 -0
  40. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/aliases.py +0 -0
  41. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/project_edit.py +0 -0
  42. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/sessions.py +0 -0
  43. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/screens/ssh.py +0 -0
  44. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/theme.py +0 -0
  45. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/widgets/__init__.py +0 -0
  46. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd/tui/widgets/spinner.py +0 -0
  47. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd.egg-info/SOURCES.txt +0 -0
  48. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd.egg-info/dependency_links.txt +0 -0
  49. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd.egg-info/entry_points.txt +0 -0
  50. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd.egg-info/requires.txt +0 -0
  51. {ccmd-2.0.3 → ccmd-2.0.5}/ccmd.egg-info/top_level.txt +0 -0
  52. {ccmd-2.0.3 → ccmd-2.0.5}/commands.yaml +0 -0
  53. {ccmd-2.0.3 → ccmd-2.0.5}/requirements.txt +0 -0
  54. {ccmd-2.0.3 → ccmd-2.0.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ccmd
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: ccmd — Agentic Project Hub. Pick a project, pick an agent, launch.
5
5
  Author-email: De Catalyst <Robert5560newton@gmail.com>
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
1
  """ccmd 2.0 — Agentic Project Hub."""
2
2
 
3
- __version__ = "2.0.3"
3
+ __version__ = "2.0.5"
4
4
  __all__ = ["__version__"]
@@ -69,8 +69,8 @@ class DirBrowserScreen(Screen[bool | None]):
69
69
  self._agent = load_config().default_agent or "claude"
70
70
 
71
71
  def compose(self) -> ComposeResult:
72
- yield Static("directory browser", id="subtitle")
73
- yield Static("", id="path-bar")
72
+ yield Static("directory browser", id="subtitle", markup=False)
73
+ yield Static("", id="path-bar", markup=False)
74
74
  yield Input(placeholder="filter this folder…", id="filter")
75
75
  with Horizontal(id="main"):
76
76
  with Vertical(id="projects-panel"):
@@ -78,10 +78,11 @@ class DirBrowserScreen(Screen[bool | None]):
78
78
  yield OptionList(id="dir-list")
79
79
  with Vertical(id="detail-panel"):
80
80
  yield Static("preview", classes="panel-title")
81
- yield Static("", id="preview")
81
+ yield Static("", id="preview", markup=False)
82
82
  yield Static(
83
- " open · up · s add project · ]/[ agent · 1-7 agent · r roots · g path · esc",
83
+ "enter open · backspace up · s add · ]/[ agent · 1-7 agent · r roots · g path · esc",
84
84
  id="footer-bar",
85
+ markup=False,
85
86
  )
86
87
  yield Footer()
87
88
 
@@ -98,9 +99,8 @@ class DirBrowserScreen(Screen[bool | None]):
98
99
  ag = get_agent(self._agent)
99
100
  ag_s = f"{ag.ascii_logo} {self._agent}" if ag else self._agent
100
101
  bar.update(
101
- f"[bold #00ffc8]{self._cwd}[/]{mark}{hidden} · "
102
- f"agent [bold #c84bff]{ag_s}[/]"
103
- + (f" [#6a6a80]{extra}[/]" if extra else "")
102
+ f"{self._cwd}{mark}{hidden} · agent {ag_s}"
103
+ + (f" {extra}" if extra else "")
104
104
  )
105
105
 
106
106
  def _render_list(self) -> None:
@@ -142,7 +142,7 @@ class DirBrowserScreen(Screen[bool | None]):
142
142
  def _render_roots(self) -> None:
143
143
  self._mode = "roots"
144
144
  self.query_one("#path-bar", Static).update(
145
- "[bold #c84bff]browse roots[/] · pick a starting point"
145
+ "browse roots · pick a starting point"
146
146
  )
147
147
  self.query_one("#list-title", Static).update("roots")
148
148
  ol = self.query_one("#dir-list", OptionList)
@@ -184,21 +184,21 @@ class DirBrowserScreen(Screen[bool | None]):
184
184
  kids = list_dir_entries(resolved, show_hidden=self._show_hidden, dirs_only=True)
185
185
  project = is_projectish(resolved)
186
186
  lines = [
187
- f"[bold #00ffc8]{resolved.name or resolved}[/]",
187
+ str(resolved.name or resolved),
188
188
  f"path {resolved}",
189
- f"project {'yes' if project else 'no (still selectable)'}",
189
+ f"project {'yes' if project else 'no (still selectable)'}",
190
190
  f"subdirs {len(kids)}",
191
191
  "",
192
- "[#6a6a80]children[/]",
192
+ "children",
193
193
  ]
194
194
  for name, _, _ in kids[:12]:
195
- lines.append(f" · {name}/")
195
+ lines.append(f" - {name}/")
196
196
  if len(kids) > 12:
197
- lines.append(f" +{len(kids) - 12} more")
197
+ lines.append(f" ... +{len(kids) - 12} more")
198
198
  lines.extend(
199
199
  [
200
200
  "",
201
- "[#6a6a80]↵ open folder · s select as project[/]",
201
+ "enter open folder · s select as project",
202
202
  ]
203
203
  )
204
204
  prev.update("\n".join(lines))
@@ -23,12 +23,11 @@ AGENT_ORDER = [a.id for a in all_agents()]
23
23
 
24
24
 
25
25
  def _agent_bar() -> str:
26
+ """Plain text — no Rich tags (logos/paths break markup easily)."""
26
27
  parts: list[str] = []
27
28
  for i, a in enumerate(detect_agents(), start=1):
28
- if a["installed"]:
29
- parts.append(f"[{a['color']}]{i}:{a['logo']}{a['id']}[/]")
30
- else:
31
- parts.append(f"[#6a6a80]{i}:{a['id']}[/]")
29
+ flag = "+" if a["installed"] else "-"
30
+ parts.append(f"{i}:{a['logo']}{a['id']}{flag}")
32
31
  return " ".join(parts)
33
32
 
34
33
 
@@ -86,11 +85,13 @@ class HubScreen(Screen):
86
85
  yield OptionList(id="project-list")
87
86
  with Vertical(id="detail-panel"):
88
87
  yield Static("detail", classes="panel-title")
89
- yield Static("Select a project", id="detail")
90
- yield Static("", id="status")
88
+ # markup=False: paths, timestamps, and key hints must never hit Rich
89
+ yield Static("Select a project", id="detail", markup=False)
90
+ yield Static("", id="status", markup=False)
91
91
  yield Static(
92
- " open · f /mnt · b browse · / filter · esc list · a agent · ] cycle · q quit",
92
+ "enter open · f /mnt · b browse · / filter · esc list · a agent · ] cycle · q quit",
93
93
  id="footer-bar",
94
+ markup=False,
94
95
  )
95
96
  yield Footer()
96
97
 
@@ -173,10 +174,10 @@ class HubScreen(Screen):
173
174
  if not p:
174
175
  detail.update(
175
176
  "Select a project\n\n"
176
- "[#6a6a80]This list is your saved registry.\n"
177
- "Press [bold]f[/] to browse /mnt and subdirs,\n"
178
- "or [bold]b[/] for home + all roots.\n"
179
- "[bold]][/] cycles default agent on selection.[/]"
177
+ "This list is your saved registry.\n"
178
+ "Press f to browse /mnt and subdirs,\n"
179
+ "or b for home + all roots.\n"
180
+ "Press ] to cycle default agent."
180
181
  )
181
182
  return
182
183
  agent = get_agent(p.default_agent)
@@ -186,29 +187,28 @@ class HubScreen(Screen):
186
187
  else p.default_agent
187
188
  )
188
189
  exists = "yes" if p.exists() else "MISSING"
189
- # agent roster
190
190
  roster: list[str] = []
191
191
  for i, a in enumerate(self._agent_info, start=1):
192
- mark = "" if a["id"] == p.default_agent else "·"
193
- ready = "" if a["installed"] else ""
192
+ mark = "*" if a["id"] == p.default_agent else " "
193
+ ready = "ok" if a["installed"] else "no"
194
194
  roster.append(f" {mark} {i} {a['logo']} {a['id']:<8} {ready}")
195
195
 
196
196
  lines = [
197
- f"[bold #00ffc8]{p.name}[/]",
197
+ p.name,
198
198
  f"id {p.id}",
199
199
  f"path {p.path}",
200
200
  f"root {_root_label(p.path)}",
201
201
  f"exists {exists}",
202
- f"agent [bold]{agent_line}[/] (default)",
203
- f"ssh {p.ssh_host or ''}",
204
- f"env {', '.join(p.env_files) or ''}",
205
- f"tags {', '.join(p.tags) or ''}",
202
+ f"agent {agent_line} (default)",
203
+ f"ssh {p.ssh_host or '-'}",
204
+ f"env {', '.join(p.env_files) or '-'}",
205
+ f"tags {', '.join(p.tags) or '-'}",
206
206
  f"opened {p.last_opened_at or 'never'}",
207
207
  "",
208
- "[bold #c84bff]agents[/] ]/[ cycle · 1-7 set · A set only · a launch",
208
+ "agents ]/[ cycle · 1-7 set · A set · a launch",
209
209
  *roster,
210
210
  "",
211
- "[#6a6a80]↵ open · d detach · b/f add from disk[/]",
211
+ "enter open · d detach · b/f add from disk",
212
212
  ]
213
213
  detail.update("\n".join(lines))
214
214
 
@@ -455,19 +455,22 @@ class HubScreen(Screen):
455
455
 
456
456
 
457
457
  def _root_label(path: str) -> str:
458
- """Short badge for where the project lives."""
458
+ """Short badge for where the project lives.
459
+
460
+ Uses angle brackets, not square ones — square brackets break Rich markup.
461
+ """
459
462
  p = path.replace("\\", "/")
460
463
  if p.startswith("/mnt/vylth"):
461
- return "[vylth]"
464
+ return "<vylth>"
462
465
  if p.startswith("/mnt/c"):
463
- return "[win-c]"
466
+ return "<win-c>"
464
467
  if p.startswith("/mnt/d"):
465
- return "[win-d]"
468
+ return "<win-d>"
466
469
  if p.startswith("/mnt/"):
467
470
  part = p.split("/")[2] if len(p.split("/")) > 2 else "mnt"
468
- return f"[mnt/{part}]"
471
+ return f"<mnt/{part}>"
469
472
  if p.startswith(str(Path.home())):
470
- return "[home]"
473
+ return "<home>"
471
474
  if p.startswith("/opt"):
472
- return "[opt]"
473
- return "[disk]"
475
+ return "<opt>"
476
+ return "<disk>"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ccmd
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: ccmd — Agentic Project Hub. Pick a project, pick an agent, launch.
5
5
  Author-email: De Catalyst <Robert5560newton@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ccmd"
7
- version = "2.0.3"
7
+ version = "2.0.5"
8
8
  description = "ccmd — Agentic Project Hub. Pick a project, pick an agent, launch."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
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
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