context-forge-cli 0.4.4__tar.gz → 0.4.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 (58) hide show
  1. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/PKG-INFO +1 -1
  2. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/app.py +8 -7
  3. context_forge_cli-0.4.5/contextforge/tui/styles.tcss +85 -0
  4. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/session_detail.py +26 -20
  5. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/session_table.py +31 -23
  6. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/stats_panel.py +9 -7
  7. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/status_bar.py +10 -9
  8. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/pyproject.toml +1 -1
  9. context_forge_cli-0.4.4/contextforge/tui/styles.tcss +0 -50
  10. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/.contextforge.toml +0 -0
  11. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/.github/workflows/publish.yml +0 -0
  12. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/.gitignore +0 -0
  13. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/.python-version +0 -0
  14. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/AGENTS.md +0 -0
  15. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/PLAN.md +0 -0
  16. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/README.md +0 -0
  17. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/__init__.py +0 -0
  18. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/__init__.py +0 -0
  19. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/altimate_code.py +0 -0
  20. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/base.py +0 -0
  21. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/claude_code.py +0 -0
  22. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/claude_desktop.py +0 -0
  23. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/codex.py +0 -0
  24. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/gemini.py +0 -0
  25. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/adapters/registry.py +0 -0
  26. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/cli.py +0 -0
  27. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/__init__.py +0 -0
  28. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/analytics.py +0 -0
  29. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/compactor.py +0 -0
  30. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/db.py +0 -0
  31. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/injector.py +0 -0
  32. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/scanner.py +0 -0
  33. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/summarizer.py +0 -0
  34. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/core/token_analyzer.py +0 -0
  35. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/mcp_server.py +0 -0
  36. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/models/__init__.py +0 -0
  37. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/models/config.py +0 -0
  38. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/models/session.py +0 -0
  39. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/__init__.py +0 -0
  40. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/__init__.py +0 -0
  41. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/tokens_panel.py +0 -0
  42. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/tui/widgets/transfer_panel.py +0 -0
  43. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/utils/__init__.py +0 -0
  44. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/utils/display.py +0 -0
  45. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/contextforge/utils/tokens.py +0 -0
  46. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/__init__.py +0 -0
  47. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/adapters/__init__.py +0 -0
  48. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/adapters/test_claude_code.py +0 -0
  49. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/conftest.py +0 -0
  50. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/__init__.py +0 -0
  51. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/test_compactor.py +0 -0
  52. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/test_db.py +0 -0
  53. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/test_injector.py +0 -0
  54. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/test_summarizer.py +0 -0
  55. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/core/test_token_analyzer.py +0 -0
  56. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/fixtures/claude_session_sample.jsonl +0 -0
  57. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/tests/test_mcp_server.py +0 -0
  58. {context_forge_cli-0.4.4 → context_forge_cli-0.4.5}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: context-forge-cli
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: Session manager and context bridge for agentic CLI tools
5
5
  Project-URL: Homepage, https://github.com/emmver/contextforge
6
6
  Project-URL: Repository, https://github.com/emmver/contextforge
@@ -19,17 +19,18 @@ class ContextForgeApp(App):
19
19
  """ContextForge dashboard — manage agentic CLI sessions."""
20
20
 
21
21
  TITLE = "ContextForge"
22
+ SUB_TITLE = "agentic session manager"
22
23
  CSS_PATH = "styles.tcss"
23
24
 
24
25
  BINDINGS = [
25
26
  Binding("q", "quit", "Quit"),
26
- Binding("r", "rescan", "Rescan"),
27
- Binding("s", "summarize", "Summarize"),
28
- Binding("t", "transfer", "Transfer"),
29
- Binding("c", "compact", "Compact"),
30
- Binding("x", "tokens", "Tokens"),
31
- Binding("a", "analytics", "Analytics"),
32
- Binding("/", "filter", "Filter"),
27
+ Binding("r", "rescan", "⟳ Rescan"),
28
+ Binding("s", "summarize", "✎ Summarize"),
29
+ Binding("t", "transfer", "⇄ Transfer"),
30
+ Binding("c", "compact", "⊛ Compact"),
31
+ Binding("x", "tokens", "# Tokens"),
32
+ Binding("a", "analytics", "▤ Analytics"),
33
+ Binding("/", "filter", "⌕ Filter"),
33
34
  ]
34
35
 
35
36
  def __init__(self, db_path: Path | None = None) -> None:
@@ -0,0 +1,85 @@
1
+ /* ContextForge TUI Styles */
2
+
3
+ /* ── Layout ─────────────────────────────────────────────── */
4
+
5
+ Screen {
6
+ layout: vertical;
7
+ }
8
+
9
+ #main-horizontal {
10
+ height: 1fr;
11
+ layout: horizontal;
12
+ }
13
+
14
+ /* ── Header ─────────────────────────────────────────────── */
15
+
16
+ Header {
17
+ background: $primary-background-darken-1;
18
+ color: $accent;
19
+ text-style: bold;
20
+ }
21
+
22
+ /* ── Footer ─────────────────────────────────────────────── */
23
+
24
+ Footer {
25
+ background: $primary-background-darken-2;
26
+ }
27
+
28
+ /* ── DataTable global tweaks ─────────────────────────────── */
29
+
30
+ DataTable > .datatable--header {
31
+ text-style: bold;
32
+ color: $accent;
33
+ background: $primary-background-darken-1;
34
+ }
35
+
36
+ DataTable > .datatable--cursor {
37
+ background: $primary;
38
+ color: $text;
39
+ }
40
+
41
+ /* ── Transfer modal ─────────────────────────────────────── */
42
+
43
+ TransferPanel {
44
+ align: center middle;
45
+ }
46
+
47
+ TransferPanel > Vertical {
48
+ width: 64;
49
+ height: auto;
50
+ max-height: 38;
51
+ border: thick $accent;
52
+ background: $surface;
53
+ padding: 1 2;
54
+ }
55
+
56
+ #panel-title {
57
+ text-style: bold;
58
+ color: $accent;
59
+ margin-bottom: 1;
60
+ padding-bottom: 1;
61
+ border-bottom: solid $primary-background-lighten-1;
62
+ }
63
+
64
+ .section-label {
65
+ text-style: bold;
66
+ margin-top: 1;
67
+ color: $text-muted;
68
+ }
69
+
70
+ #btn-row {
71
+ margin-top: 2;
72
+ height: auto;
73
+ layout: horizontal;
74
+ align: right middle;
75
+ }
76
+
77
+ #btn-row Button {
78
+ margin-left: 1;
79
+ }
80
+
81
+ /* ── Notifications ──────────────────────────────────────── */
82
+
83
+ Toast {
84
+ border: tall $accent;
85
+ }
@@ -11,21 +11,23 @@ from textual.widget import Widget
11
11
  from textual.widgets import Markdown, Static
12
12
 
13
13
  TOOL_COLORS = {
14
- "claude_code": "cyan",
15
- "codex": "green",
16
- "altimate_code": "magenta",
14
+ "claude_code": "cyan",
15
+ "codex": "green",
16
+ "altimate_code": "magenta",
17
17
  "claude_desktop": "yellow",
18
+ "gemini": "blue",
18
19
  }
19
20
  TOOL_LABELS = {
20
- "claude_code": "Claude Code",
21
- "codex": "Codex",
22
- "altimate_code": "altimate",
23
- "claude_desktop": "Desktop",
21
+ "claude_code": "◆ Claude Code",
22
+ "codex": "⬡ Codex",
23
+ "altimate_code": "⚡ Altimate",
24
+ "claude_desktop": "◇ Claude Desktop",
25
+ "gemini": "✦ Gemini",
24
26
  }
25
27
 
26
28
 
27
29
  def _meta_line(label: str, value: str, color: str = "cyan") -> str:
28
- return f"[bold {color}]{label:<10}[/bold {color}] {value}"
30
+ return f"[dim]{label:<10}[/dim] {value}"
29
31
 
30
32
 
31
33
  def _fmt_tokens(n: int | None) -> str:
@@ -75,11 +77,14 @@ class SessionDetail(Widget):
75
77
  color: $text-disabled;
76
78
  margin: 4 0;
77
79
  text-align: center;
80
+ text-style: italic;
78
81
  }
79
82
  SessionDetail #detail-title {
80
83
  text-style: bold;
81
84
  color: $accent;
82
85
  margin-bottom: 1;
86
+ padding-bottom: 1;
87
+ border-bottom: solid $primary-background-lighten-1;
83
88
  }
84
89
  SessionDetail #detail-meta-block {
85
90
  margin-bottom: 1;
@@ -88,8 +93,9 @@ class SessionDetail(Widget):
88
93
  }
89
94
  SessionDetail #detail-summary-label {
90
95
  text-style: bold;
91
- color: $text-muted;
96
+ color: $accent;
92
97
  margin-bottom: 1;
98
+ margin-top: 1;
93
99
  }
94
100
  SessionDetail Markdown {
95
101
  background: transparent;
@@ -111,11 +117,11 @@ class SessionDetail(Widget):
111
117
  yield Static("", id="detail-status")
112
118
  yield Static("", id="detail-tags")
113
119
  yield Static("", id="detail-id")
114
- yield Static("── Summary ──", id="detail-summary-label")
120
+ yield Static("✎ Summary", id="detail-summary-label")
115
121
  yield Markdown("", id="detail-summary-md")
116
122
 
117
123
  def on_mount(self) -> None:
118
- self.border_title = "Detail"
124
+ self.border_title = "◈ Detail"
119
125
  self.query_one("#detail-summary-label").display = False
120
126
  self.query_one("#detail-meta-block").display = False
121
127
  self.query_one("#detail-title").display = False
@@ -168,15 +174,15 @@ class SessionDetail(Widget):
168
174
  self.query_one("#detail-meta-block").display = True
169
175
  self.query_one("#detail-summary-label").display = True
170
176
 
171
- self.query_one("#detail-title", Static).update(f"[bold accent]{title}[/bold accent]")
172
- self.query_one("#detail-tool", Static).update(_meta_line("Tool", tool_markup, tool_color))
173
- self.query_one("#detail-cwd", Static).update(_meta_line("CWD", f"[dim]{cwd}[/dim]", "dim"))
174
- self.query_one("#detail-tokens", Static).update(_meta_line("Tokens", tok_markup, "dim"))
175
- self.query_one("#detail-created", Static).update(_meta_line("Created", f"[dim]{created_str}[/dim]", "dim"))
176
- self.query_one("#detail-updated", Static).update(_meta_line("Updated", f"[dim]{updated_str}[/dim]", "dim"))
177
- self.query_one("#detail-status", Static).update(_meta_line("Status", status, "dim"))
178
- self.query_one("#detail-tags", Static).update(_meta_line("Tags", tags, "dim"))
179
- self.query_one("#detail-id", Static).update(_meta_line("ID", f"[dim]{session_id}[/dim]", "dim"))
177
+ self.query_one("#detail-title", Static).update(f"[bold]{title}[/bold]")
178
+ self.query_one("#detail-tool", Static).update(_meta_line("Tool", tool_markup))
179
+ self.query_one("#detail-cwd", Static).update(_meta_line("Project", f"[dim]{cwd}[/dim]"))
180
+ self.query_one("#detail-tokens", Static).update(_meta_line("Tokens", tok_markup))
181
+ self.query_one("#detail-created", Static).update(_meta_line("Created", f"[dim]{created_str}[/dim]"))
182
+ self.query_one("#detail-updated", Static).update(_meta_line("Updated", f"[dim]{updated_str}[/dim]"))
183
+ self.query_one("#detail-status", Static).update(_meta_line("Status", f"[dim]{status}[/dim]"))
184
+ self.query_one("#detail-tags", Static).update(_meta_line("Tags", f"[dim]{tags}[/dim]"))
185
+ self.query_one("#detail-id", Static).update(_meta_line("ID", f"[dim]{session_id}[/dim]"))
180
186
 
181
187
  md = self.query_one("#detail-summary-md", Markdown)
182
188
  self.app.call_later(md.update, summary)
@@ -12,31 +12,36 @@ from textual.reactive import reactive
12
12
  from textual.widget import Widget
13
13
  from textual.widgets import Button, DataTable, Input, Label
14
14
 
15
- TOOL_EMOJI = {
16
- "claude_code": "🔵",
17
- "codex": "🟢",
18
- "altimate_code": "🟣",
19
- "claude_desktop": "🟡",
15
+ # Unicode symbols that evoke each tool brand (terminals can't render images)
16
+ TOOL_ICON = {
17
+ "claude_code": "◆", # Anthropic — solid diamond
18
+ "codex": "⬡", # OpenAI — hexagon
19
+ "altimate_code": "⚡", # Altimate — lightning
20
+ "claude_desktop": "◇", # Claude Desktop — open diamond
21
+ "gemini": "✦", # Google Gemini — four-pointed star
20
22
  }
21
23
 
22
24
  TOOL_MARKUP = {
23
- "claude_code": "[cyan]🔵 CC[/cyan]",
24
- "codex": "[green]🟢 Codex[/green]",
25
- "altimate_code": "[magenta]🟣 Alt[/magenta]",
26
- "claude_desktop": "[yellow]🟡 Desktop[/yellow]",
25
+ "claude_code": "[cyan]◆ Claude[/cyan]",
26
+ "codex": "[green]⬡ Codex[/green]",
27
+ "altimate_code": "[magenta]⚡ Alt[/magenta]",
28
+ "claude_desktop": "[yellow]◇ Desktop[/yellow]",
29
+ "gemini": "[blue]✦ Gemini[/blue]",
27
30
  }
28
31
 
29
32
  TOOL_DISPLAY = {
30
- "claude_code": "CC",
31
- "codex": "Codex",
32
- "altimate_code": "Alt",
33
- "claude_desktop": "Desktop",
33
+ "claude_code": "◆ Claude",
34
+ "codex": "⬡ Codex",
35
+ "altimate_code": "⚡ Alt",
36
+ "claude_desktop": "◇ Desktop",
37
+ "gemini": "✦ Gemini",
34
38
  }
35
39
 
36
40
  _FTOOL_MAP = {
37
41
  "ftool-all": None,
38
42
  "ftool-cc": "claude_code",
39
43
  "ftool-codex": "codex",
44
+ "ftool-gem": "gemini",
40
45
  "ftool-alt": "altimate_code",
41
46
  }
42
47
 
@@ -89,14 +94,16 @@ class SessionTable(Widget):
89
94
  SessionTable #filter-label {
90
95
  width: auto;
91
96
  margin-right: 1;
92
- color: $text-muted;
97
+ color: $accent;
98
+ text-style: bold;
93
99
  }
94
100
  SessionTable #filter-input {
95
- width: 28;
101
+ width: 26;
96
102
  margin-right: 1;
103
+ border: tall $primary;
97
104
  }
98
105
  SessionTable .filter-tool-btn {
99
- min-width: 7;
106
+ min-width: 9;
100
107
  height: 1;
101
108
  margin-right: 1;
102
109
  background: $surface;
@@ -147,14 +154,15 @@ class SessionTable(Widget):
147
154
  with Horizontal(id="filter-bar", classes="hidden"):
148
155
  yield Label("Filter:", id="filter-label")
149
156
  yield Input(placeholder="title or project…", id="filter-input")
150
- yield Button("All", id="ftool-all", classes="filter-tool-btn active")
151
- yield Button("CC", id="ftool-cc", classes="filter-tool-btn")
152
- yield Button("Codex", id="ftool-codex", classes="filter-tool-btn")
153
- yield Button("Alt", id="ftool-alt", classes="filter-tool-btn")
154
- yield DataTable(cursor_type="row", zebra_stripes=True)
157
+ yield Button("All", id="ftool-all", classes="filter-tool-btn active")
158
+ yield Button("◆ CC", id="ftool-cc", classes="filter-tool-btn")
159
+ yield Button("⬡ Codex", id="ftool-codex", classes="filter-tool-btn")
160
+ yield Button("✦ Gem", id="ftool-gem", classes="filter-tool-btn")
161
+ yield Button("⚡ Alt", id="ftool-alt", classes="filter-tool-btn")
162
+ yield DataTable(cursor_type="row", zebra_stripes=True, id="sessions-datatable")
155
163
 
156
164
  def on_mount(self) -> None:
157
- self.border_title = "Sessions"
165
+ self.border_title = "◈ Sessions"
158
166
  table = self.query_one(DataTable)
159
167
  table.add_columns("Tool", "Title", "Updated", "Tokens", "ID")
160
168
  self.reload()
@@ -210,7 +218,7 @@ class SessionTable(Widget):
210
218
  tool_label = TOOL_MARKUP.get(tool, f"⚪ {tool}")
211
219
 
212
220
  from contextforge.utils.display import _clean_title
213
- title = _clean_title(row.get("title") or "", max_len=38) or "(no title)"
221
+ title = _clean_title(row.get("title") or "", max_len=40) or "(no title)"
214
222
 
215
223
  updated_ms = row.get("updated_at") or 0
216
224
  try:
@@ -16,16 +16,18 @@ _BLOCKS = " ▏▎▍▌▋▊▉█" # 9 levels: 0/8 → 8/8 of a cell
16
16
  _SPARK = "▁▂▃▄▅▆▇█" # 8 vertical height levels
17
17
 
18
18
  TOOL_COLORS = {
19
- "claude_code": "cyan",
20
- "codex": "green",
21
- "altimate_code": "magenta",
19
+ "claude_code": "cyan",
20
+ "codex": "green",
21
+ "altimate_code": "magenta",
22
22
  "claude_desktop": "yellow",
23
+ "gemini": "blue",
23
24
  }
24
25
  TOOL_LABELS = {
25
- "claude_code": "Claude Code",
26
- "codex": "Codex",
27
- "altimate_code": "altimate",
28
- "claude_desktop": "Desktop",
26
+ "claude_code": "◆ Claude Code",
27
+ "codex": "⬡ Codex",
28
+ "altimate_code": "⚡ Altimate",
29
+ "claude_desktop": "◇ Desktop",
30
+ "gemini": "✦ Gemini",
29
31
  }
30
32
 
31
33
  WINDOW_LABELS = {
@@ -64,23 +64,24 @@ class StatusBar(Widget):
64
64
 
65
65
  tool_parts = []
66
66
  labels = {
67
- "claude_code": "CC",
68
- "codex": "Codex",
69
- "altimate_code": "Alt",
70
- "claude_desktop": "Desktop",
67
+ "claude_code": "◆ CC",
68
+ "codex": "⬡ Codex",
69
+ "altimate_code": "⚡ Alt",
70
+ "claude_desktop": "◇ Desktop",
71
+ "gemini": "✦ Gemini",
71
72
  }
72
73
  for tool, label in labels.items():
73
74
  n = counts.get(tool, 0)
74
75
  if n:
75
- tool_parts.append(f"{label}:{n}")
76
+ tool_parts.append(f"{label} {n}")
76
77
 
77
78
  tok_str = _fmt_tokens(total_tokens)
78
79
  self.query_one("#status-counts").update(
79
- f"Sessions — {' │ '.join(tool_parts)} │ Total:{len(rows)} │ {tok_str}"
80
+ f" {' [dim]│[/dim] '.join(tool_parts)} [dim]│[/dim] [bold]{len(rows)}[/bold] sessions [dim]│[/dim] {tok_str}"
80
81
  )
81
82
 
82
83
  now = datetime.now(timezone.utc).strftime("%H:%M:%S")
83
- self.query_one("#status-scan-time").update(f"Updated {now}")
84
+ self.query_one("#status-scan-time").update(f"[dim]⟳ {now}[/dim]")
84
85
 
85
86
  def set_filter_indicator(
86
87
  self, text: str, tool: str | None, match_count: int
@@ -94,9 +95,9 @@ class StatusBar(Widget):
94
95
  if text:
95
96
  parts.append(f'"{text}"')
96
97
  if tool:
97
- short = {"claude_code": "CC", "codex": "Codex", "altimate_code": "Alt", "claude_desktop": "Desktop"}.get(tool, tool)
98
+ short = {"claude_code": "◆ CC", "codex": "⬡ Codex", "altimate_code": "⚡ Alt", "claude_desktop": "◇ Desktop", "gemini": "✦ Gemini"}.get(tool, tool)
98
99
  parts.append(short)
99
100
 
100
101
  self.query_one("#status-filter", Static).update(
101
- f"[yellow]Filter: {' + '.join(parts)} ({match_count} matches)[/yellow]"
102
+ f"[yellow]⌕ {' + '.join(parts)} [dim]({match_count} matches)[/dim][/yellow]"
102
103
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "context-forge-cli"
3
- version = "0.4.4"
3
+ version = "0.4.5"
4
4
  description = "Session manager and context bridge for agentic CLI tools"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -1,50 +0,0 @@
1
- /* ContextForge TUI Styles */
2
-
3
- /* ── Layout ─────────────────────────────────────────────── */
4
-
5
- Screen {
6
- layout: vertical;
7
- }
8
-
9
- #main-horizontal {
10
- height: 1fr;
11
- layout: horizontal;
12
- }
13
-
14
- /* ── Transfer modal ─────────────────────────────────────── */
15
-
16
- TransferPanel {
17
- align: center middle;
18
- }
19
-
20
- TransferPanel > Vertical {
21
- width: 64;
22
- height: auto;
23
- max-height: 38;
24
- border: thick $primary;
25
- background: $surface;
26
- padding: 1 2;
27
- }
28
-
29
- #panel-title {
30
- text-style: bold;
31
- color: $accent;
32
- margin-bottom: 1;
33
- }
34
-
35
- .section-label {
36
- text-style: bold;
37
- margin-top: 1;
38
- color: $text-muted;
39
- }
40
-
41
- #btn-row {
42
- margin-top: 2;
43
- height: auto;
44
- layout: horizontal;
45
- align: right middle;
46
- }
47
-
48
- #btn-row Button {
49
- margin-left: 1;
50
- }