emdash-cli 0.1.35__py3-none-any.whl → 0.1.67__py3-none-any.whl

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 (50) hide show
  1. emdash_cli/client.py +41 -22
  2. emdash_cli/clipboard.py +30 -61
  3. emdash_cli/commands/__init__.py +2 -2
  4. emdash_cli/commands/agent/__init__.py +14 -0
  5. emdash_cli/commands/agent/cli.py +100 -0
  6. emdash_cli/commands/agent/constants.py +63 -0
  7. emdash_cli/commands/agent/file_utils.py +178 -0
  8. emdash_cli/commands/agent/handlers/__init__.py +51 -0
  9. emdash_cli/commands/agent/handlers/agents.py +449 -0
  10. emdash_cli/commands/agent/handlers/auth.py +69 -0
  11. emdash_cli/commands/agent/handlers/doctor.py +319 -0
  12. emdash_cli/commands/agent/handlers/hooks.py +121 -0
  13. emdash_cli/commands/agent/handlers/index.py +183 -0
  14. emdash_cli/commands/agent/handlers/mcp.py +183 -0
  15. emdash_cli/commands/agent/handlers/misc.py +319 -0
  16. emdash_cli/commands/agent/handlers/registry.py +72 -0
  17. emdash_cli/commands/agent/handlers/rules.py +411 -0
  18. emdash_cli/commands/agent/handlers/sessions.py +168 -0
  19. emdash_cli/commands/agent/handlers/setup.py +715 -0
  20. emdash_cli/commands/agent/handlers/skills.py +478 -0
  21. emdash_cli/commands/agent/handlers/telegram.py +475 -0
  22. emdash_cli/commands/agent/handlers/todos.py +119 -0
  23. emdash_cli/commands/agent/handlers/verify.py +653 -0
  24. emdash_cli/commands/agent/help.py +236 -0
  25. emdash_cli/commands/agent/interactive.py +842 -0
  26. emdash_cli/commands/agent/menus.py +760 -0
  27. emdash_cli/commands/agent/onboarding.py +619 -0
  28. emdash_cli/commands/agent/session_restore.py +210 -0
  29. emdash_cli/commands/agent.py +7 -1321
  30. emdash_cli/commands/index.py +111 -13
  31. emdash_cli/commands/registry.py +635 -0
  32. emdash_cli/commands/server.py +99 -40
  33. emdash_cli/commands/skills.py +72 -6
  34. emdash_cli/design.py +328 -0
  35. emdash_cli/diff_renderer.py +438 -0
  36. emdash_cli/integrations/__init__.py +1 -0
  37. emdash_cli/integrations/telegram/__init__.py +15 -0
  38. emdash_cli/integrations/telegram/bot.py +402 -0
  39. emdash_cli/integrations/telegram/bridge.py +865 -0
  40. emdash_cli/integrations/telegram/config.py +155 -0
  41. emdash_cli/integrations/telegram/formatter.py +385 -0
  42. emdash_cli/main.py +52 -2
  43. emdash_cli/server_manager.py +70 -10
  44. emdash_cli/sse_renderer.py +659 -167
  45. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.67.dist-info}/METADATA +2 -4
  46. emdash_cli-0.1.67.dist-info/RECORD +63 -0
  47. emdash_cli/commands/swarm.py +0 -86
  48. emdash_cli-0.1.35.dist-info/RECORD +0 -30
  49. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.67.dist-info}/WHEEL +0 -0
  50. {emdash_cli-0.1.35.dist-info → emdash_cli-0.1.67.dist-info}/entry_points.txt +0 -0
@@ -23,16 +23,18 @@ def index():
23
23
 
24
24
  @index.command("start")
25
25
  @click.argument("repo_path", required=False)
26
- @click.option("--changed-only", is_flag=True, help="Only index changed files")
27
- @click.option("--skip-git", is_flag=True, help="Skip git history indexing")
28
- @click.option("--github-prs", default=0, help="Number of GitHub PRs to index")
26
+ @click.option("--full", is_flag=True, help="Force full reindex (default: incremental)")
27
+ @click.option("--with-git", is_flag=True, help="Include git history (Layer B)")
28
+ @click.option("--with-github", is_flag=True, help="Include GitHub PRs (Layer C)")
29
+ @click.option("--github-prs", default=50, help="Number of GitHub PRs to index (when --with-github)")
29
30
  @click.option("--detect-communities", is_flag=True, default=True, help="Run community detection")
30
31
  @click.option("--describe-communities", is_flag=True, help="Use LLM to describe communities")
31
32
  @click.option("--model", "-m", default=None, help="Model for community descriptions")
32
33
  def index_start(
33
34
  repo_path: str | None,
34
- changed_only: bool,
35
- skip_git: bool,
35
+ full: bool,
36
+ with_git: bool,
37
+ with_github: bool,
36
38
  github_prs: int,
37
39
  detect_communities: bool,
38
40
  describe_communities: bool,
@@ -42,11 +44,18 @@ def index_start(
42
44
 
43
45
  If REPO_PATH is not provided, indexes the current directory.
44
46
 
47
+ By default, indexes only code structure (Layer A - AST parsing).
48
+ Git history (Layer B) and GitHub PRs (Layer C) are skipped unless enabled.
49
+
50
+ Environment variables:
51
+ EMDASH_INDEX_GIT=true Enable git history indexing
52
+ EMDASH_INDEX_GITHUB=true Enable GitHub PR indexing
53
+
45
54
  Examples:
46
- emdash index start # Index current directory
47
- emdash index start /path/to/repo # Index specific repo
48
- emdash index start --changed-only # Only index changed files
49
- emdash index start --github-prs 50 # Also index 50 PRs
55
+ emdash index start # Code only (Layer A)
56
+ emdash index start --with-git # Include git history
57
+ emdash index start --with-github # Include GitHub PRs
58
+ emdash index start --full # Force full reindex
50
59
  """
51
60
  # Default to current directory
52
61
  if not repo_path:
@@ -58,11 +67,20 @@ def index_start(
58
67
 
59
68
  console.print(f"\n[bold cyan]Indexing[/bold cyan] {repo_path}\n")
60
69
 
70
+ # Check environment variables for Layer B and C
71
+ env_index_git = os.environ.get("EMDASH_INDEX_GIT", "").lower() == "true"
72
+ env_index_github = os.environ.get("EMDASH_INDEX_GITHUB", "").lower() == "true"
73
+
74
+ # Enable git/github if flag passed OR env var set
75
+ index_git = with_git or env_index_git
76
+ index_github = with_github or env_index_github
77
+
61
78
  # Build options
79
+ # Incremental mode is default (changed_only=True), unless --full is passed
62
80
  options = {
63
- "changed_only": changed_only,
64
- "index_git": not skip_git,
65
- "index_github": github_prs,
81
+ "changed_only": not full,
82
+ "index_git": index_git,
83
+ "index_github": github_prs if index_github else 0,
66
84
  "detect_communities": detect_communities,
67
85
  "describe_communities": describe_communities,
68
86
  }
@@ -82,7 +100,7 @@ def index_start(
82
100
  ) as progress:
83
101
  task = progress.add_task("Starting...", total=100)
84
102
 
85
- for line in client.index_start_stream(repo_path, changed_only):
103
+ for line in client.index_start_stream(repo_path, not full):
86
104
  line = line.strip()
87
105
  if line.startswith("event: "):
88
106
  continue
@@ -160,6 +178,86 @@ def _show_completion(repo_path: str, stats: dict, client: EmdashClient) -> None:
160
178
  console.print()
161
179
 
162
180
 
181
+ @index.command("hook")
182
+ @click.argument("action", type=click.Choice(["install", "uninstall"]))
183
+ @click.argument("repo_path", required=False)
184
+ def index_hook(action: str, repo_path: str | None):
185
+ """Install or uninstall the post-commit hook for automatic indexing.
186
+
187
+ The hook runs 'emdash index start' after each commit to keep the index updated.
188
+
189
+ Examples:
190
+ emdash index hook install # Install in current repo
191
+ emdash index hook install /path/repo # Install in specific repo
192
+ emdash index hook uninstall # Remove the hook
193
+ """
194
+ from pathlib import Path
195
+
196
+ # Default to current directory
197
+ if not repo_path:
198
+ repo_path = os.getcwd()
199
+
200
+ hooks_dir = Path(repo_path) / ".git" / "hooks"
201
+ hook_path = hooks_dir / "post-commit"
202
+
203
+ if not hooks_dir.exists():
204
+ console.print(f"[red]Error:[/red] Not a git repository: {repo_path}")
205
+ raise click.Abort()
206
+
207
+ hook_content = """#!/bin/sh
208
+ # emdash post-commit hook - auto-reindex on commit
209
+ # Installed by: emdash index hook install
210
+
211
+ # Run indexing in background to not block the commit
212
+ emdash index start > /dev/null 2>&1 &
213
+ """
214
+
215
+ if action == "install":
216
+ # Check if hook already exists
217
+ if hook_path.exists():
218
+ existing = hook_path.read_text()
219
+ if "emdash" in existing:
220
+ console.print("[yellow]Hook already installed[/yellow]")
221
+ return
222
+ else:
223
+ # Append to existing hook
224
+ console.print("[yellow]Appending to existing post-commit hook[/yellow]")
225
+ with open(hook_path, "a") as f:
226
+ f.write("\n# emdash auto-index\nemdash index start > /dev/null 2>&1 &\n")
227
+ else:
228
+ # Create new hook
229
+ hook_path.write_text(hook_content)
230
+
231
+ # Make executable
232
+ hook_path.chmod(0o755)
233
+ console.print(f"[green]Post-commit hook installed:[/green] {hook_path}")
234
+
235
+ elif action == "uninstall":
236
+ if not hook_path.exists():
237
+ console.print("[yellow]No post-commit hook found[/yellow]")
238
+ return
239
+
240
+ existing = hook_path.read_text()
241
+ if "emdash" not in existing:
242
+ console.print("[yellow]No emdash hook found in post-commit[/yellow]")
243
+ return
244
+
245
+ # Check if it's our hook entirely or just contains our line
246
+ if existing.strip() == hook_content.strip():
247
+ # It's only our hook, remove the file
248
+ hook_path.unlink()
249
+ console.print("[green]Post-commit hook removed[/green]")
250
+ else:
251
+ # Remove just our lines
252
+ lines = existing.split("\n")
253
+ new_lines = [
254
+ line for line in lines
255
+ if "emdash" not in line and "auto-reindex" not in line
256
+ ]
257
+ hook_path.write_text("\n".join(new_lines))
258
+ console.print("[green]Emdash hook lines removed from post-commit[/green]")
259
+
260
+
163
261
  @index.command("status")
164
262
  @click.argument("repo_path", required=False)
165
263
  def index_status(repo_path: str | None):