spex-cli 0.1.0__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 (33) hide show
  1. spex_cli-0.1.0/.github/workflows/tests.yml +30 -0
  2. spex_cli-0.1.0/.gitignore +34 -0
  3. spex_cli-0.1.0/PKG-INFO +54 -0
  4. spex_cli-0.1.0/README.md +38 -0
  5. spex_cli-0.1.0/docs/logo.png +0 -0
  6. spex_cli-0.1.0/docs/spex-user-guide.md +159 -0
  7. spex_cli-0.1.0/pyproject.toml +39 -0
  8. spex_cli-0.1.0/scripts/deploy.sh +82 -0
  9. spex_cli-0.1.0/src/spex_cli/__init__.py +69 -0
  10. spex_cli-0.1.0/src/spex_cli/_help.py +130 -0
  11. spex_cli-0.1.0/src/spex_cli/agents.py +33 -0
  12. spex_cli-0.1.0/src/spex_cli/claude_settings/settings.json +21 -0
  13. spex_cli-0.1.0/src/spex_cli/disable.py +173 -0
  14. spex_cli-0.1.0/src/spex_cli/enable.py +287 -0
  15. spex_cli-0.1.0/src/spex_cli/hooks/hook_trace_commit.py +58 -0
  16. spex_cli-0.1.0/src/spex_cli/hooks/post-commit +6 -0
  17. spex_cli-0.1.0/src/spex_cli/models.py +326 -0
  18. spex_cli-0.1.0/src/spex_cli/skills/init.md +36 -0
  19. spex_cli-0.1.0/src/spex_cli/skills/spex/SKILL.md +311 -0
  20. spex_cli-0.1.0/src/spex_cli/skills/spex/references/conflict-resolution.md +34 -0
  21. spex_cli-0.1.0/src/spex_cli/skills/spex/references/knowledge-capture.md +124 -0
  22. spex_cli-0.1.0/src/spex_cli/skills/spex/references/memory-research.md +42 -0
  23. spex_cli-0.1.0/src/spex_cli/skills/spex/references/orchestration-guide.md +397 -0
  24. spex_cli-0.1.0/src/spex_cli/skills/spex-onboard/SKILL.md +207 -0
  25. spex_cli-0.1.0/src/spex_cli/skills/spex-reflect/SKILL.md +381 -0
  26. spex_cli-0.1.0/src/spex_cli/spex.py +1580 -0
  27. spex_cli-0.1.0/tests/benchmark_spex.py +76 -0
  28. spex_cli-0.1.0/tests/test_blame.py +152 -0
  29. spex_cli-0.1.0/tests/test_disable.py +299 -0
  30. spex_cli-0.1.0/tests/test_models.py +74 -0
  31. spex_cli-0.1.0/tests/test_spex.py +289 -0
  32. spex_cli-0.1.0/tests/test_spex_state.py +104 -0
  33. spex_cli-0.1.0/uv.lock +834 -0
@@ -0,0 +1,30 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+
21
+ - name: Install dependencies
22
+ run: pip install -e ".[test]"
23
+
24
+ - name: Lint
25
+ run: |
26
+ pip install ruff
27
+ ruff check .
28
+
29
+ - name: Run tests
30
+ run: pytest
@@ -0,0 +1,34 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Environment variables
16
+ .env
17
+ .env.local
18
+ .env*.local
19
+
20
+ # Editor directories and files
21
+ .vscode/*
22
+ !.vscode/extensions.json
23
+ .idea
24
+ .DS_Store
25
+ *.suo
26
+ *.ntvs*
27
+ *.njsproj
28
+ *.sln
29
+ *.sw?
30
+ __pycache__/
31
+ *.pyc
32
+ *.pyo
33
+ .vite
34
+ .pypirc
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: spex-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for managing requirements and decisions
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: questionary>=2.0
7
+ Requires-Dist: rich>=13.0
8
+ Requires-Dist: ruff>=0.15.1
9
+ Provides-Extra: dev
10
+ Requires-Dist: build>=1.0.0; extra == 'dev'
11
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
12
+ Provides-Extra: test
13
+ Requires-Dist: pytest-cov>=4.0; extra == 'test'
14
+ Requires-Dist: pytest>=8; extra == 'test'
15
+ Description-Content-Type: text/markdown
16
+
17
+ <p align="center">
18
+ <img src="docs/logo.png" alt="speX Logo" width="120" />
19
+ </p>
20
+
21
+ <h1 align="center">🌋Spex CLI</h1>
22
+
23
+ <p align="center">
24
+ <strong>Autonomous engineering experience enabled.</strong>
25
+ <br />
26
+ <em>Built by the MagmaAI Team</em>
27
+ </p>
28
+
29
+ <p align="center">
30
+ <a href="#overview">Overview</a> •
31
+ <a href="#features">Features</a> •
32
+ <a href="#getting-started">Getting Started</a> •
33
+ <a href="#project-structure">Project Structure</a> •
34
+ <a href="#development">Development</a> •
35
+ <a href="#contributing">Contributing</a>
36
+ </p>
37
+
38
+ ---
39
+
40
+ ## Deployment
41
+
42
+ To deploy a new version of `spex-cli` to PyPI, use the provided deployment script:
43
+
44
+ ```bash
45
+ ./scripts/deploy.sh
46
+ ```
47
+
48
+ This script will:
49
+ 1. Verify no uncommitted changes exist.
50
+ 2. Build the package using `uv` (if available) or `build`.
51
+ 3. Check the distribution packages with `twine`.
52
+ 4. Prompt for upload to TestPyPI or PyPI.
53
+
54
+ Make sure you have your PyPI credentials configured in `~/.pypirc` or set via environment variables (`TWINE_USERNAME` and `TWINE_PASSWORD`).
@@ -0,0 +1,38 @@
1
+ <p align="center">
2
+ <img src="docs/logo.png" alt="speX Logo" width="120" />
3
+ </p>
4
+
5
+ <h1 align="center">🌋Spex CLI</h1>
6
+
7
+ <p align="center">
8
+ <strong>Autonomous engineering experience enabled.</strong>
9
+ <br />
10
+ <em>Built by the MagmaAI Team</em>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="#overview">Overview</a> •
15
+ <a href="#features">Features</a> •
16
+ <a href="#getting-started">Getting Started</a> •
17
+ <a href="#project-structure">Project Structure</a> •
18
+ <a href="#development">Development</a> •
19
+ <a href="#contributing">Contributing</a>
20
+ </p>
21
+
22
+ ---
23
+
24
+ ## Deployment
25
+
26
+ To deploy a new version of `spex-cli` to PyPI, use the provided deployment script:
27
+
28
+ ```bash
29
+ ./scripts/deploy.sh
30
+ ```
31
+
32
+ This script will:
33
+ 1. Verify no uncommitted changes exist.
34
+ 2. Build the package using `uv` (if available) or `build`.
35
+ 3. Check the distribution packages with `twine`.
36
+ 4. Prompt for upload to TestPyPI or PyPI.
37
+
38
+ Make sure you have your PyPI credentials configured in `~/.pypirc` or set via environment variables (`TWINE_USERNAME` and `TWINE_PASSWORD`).
Binary file
@@ -0,0 +1,159 @@
1
+ # Spex Skills: A User Guide
2
+
3
+ The Spex ecosystem is designed to bring structure, traceability, and knowledge retention to your development process. It consists of two core skills: `spex-onboard` for initial setup and `spex` for orchestrating development tasks.
4
+
5
+ This guide will help you understand when and how to use each skill effectively.
6
+
7
+ ## 1. `spex-onboard`: Setting Up Your Project
8
+
9
+ The `spex-onboard` skill is the first step to integrating your project with Spex. Its sole purpose is to analyze your codebase, identify all the distinct applications and reusable libraries within it, and create a record of them. This record is crucial for all future Spex operations.
10
+
11
+ ### When to Use `spex-onboard`
12
+
13
+ You should use this skill in two primary scenarios:
14
+
15
+ 1. **Initial Project Setup:** When you first start using Spex on a new or existing codebase. This is a mandatory first step.
16
+ 2. **Major Codebase Restructuring:** If you add or remove entire applications or libraries (e.g., adding a new microservice, monolothic repo refactor).
17
+
18
+ **Example Invocation:**
19
+ ```
20
+ spex-onboard analyze the codebase
21
+ ```
22
+
23
+ ### How It Works
24
+
25
+ When invoked, `spex-onboard` performs the following automated steps:
26
+
27
+ 1. **Detects Code:** It scans your project for common application and library indicators.
28
+ * **Supported Types:** Node.js (`package.json`), Python (`requirements.txt`, `pyproject.toml`), Rust (`Cargo.toml`), Go (`go.mod`), Docker (`Dockerfile`), Kubernetes manifests, and more.
29
+ 2. **Identifies Components:** It categorizes each finding as either an `application` (deployable service/site) or a `library` (reusable package).
30
+ 3. **Prompts for Owners (Interactive):** For each component found, it will pause and ask you: *"Who is the owner/maintainer?"*. You can provide a name/team or press Enter to skip.
31
+ 4. **Persists to Memory:** It saves this structural map to `.spex/memory/apps.jsonl`. This file is the "atlas" for all subsequent Spex operations.
32
+ 5. **Suggests Next Steps:** Finally, it identifies potential documentation files (e.g., `README.md`, `ARCHITECTURE.md`) and suggests using them to "teach" the agent (see **Section 4: Knowledge Capture**).
33
+
34
+ ---
35
+
36
+ ## 2. `spex`: Orchestrating Development Work
37
+
38
+ The `spex` skill is your day-to-day workhorse. It intelligently sizes up your request and directs it into one of two powerful workflows: a **Lightweight Flow** for small fixes or a **Full State Machine** for larger features.
39
+
40
+ ### Choosing the Right Flow: Small vs. Large Requests
41
+
42
+ The `spex` skill automatically evaluates your request to decide which path to take. Here’s how it differentiates:
43
+
44
+ | Request Type | Criteria | Examples |
45
+ | :--- | :--- | :--- |
46
+ | **Small** | Affects a single file, is an unambiguous bug fix, or a minor cosmetic change with no architectural impact. | "Fix the typo on the login button."<br>"Adjust the margin on the user profile card."<br>"Refactor this function to be more readable." |
47
+ | **Large** | Involves multiple files, introduces new functionality, requires architectural decisions, or is ambiguous. | "Build a new settings page."<br>"Implement two-factor authentication."<br>"Redesign the data processing pipeline." |
48
+
49
+ ### A. The Lightweight Flow (for Small Requests)
50
+
51
+ This flow is designed to be fast, efficient, and minimally intrusive for everyday tasks. It skips the heavy planning phase but ensures code quality and knowledge retention.
52
+
53
+ #### When to Use
54
+
55
+ You should use the lightweight flow for small, self-contained changes. Simply state your request directly.
56
+
57
+ **Example Invocations:**
58
+ * `"Fix the bug where the user's name doesn't update in the header."`
59
+ * `"Change the primary button color to the new brand blue."`
60
+ * `"Add a loading spinner while the data is fetching."`
61
+
62
+ #### How It Works
63
+
64
+ 1. **Research Memory:** It checks Spex's memory for existing policies or decisions to ensure compliance.
65
+ 2. **Execute Directly:** It performs the change using Test-Driven Development (TDD) where applicable.
66
+ 3. **Memorize (Capture Knowledge):** After completion, it automatically extracts requirements and decisions and saves them to memory.
67
+
68
+ **Important:** This flow does **not** create a feature folder (`.spex/<feature-name>`). It keeps your repository clean for small, tactical changes.
69
+
70
+ ### B. The Full State Machine (for Large Requests)
71
+
72
+ This is a structured, traceable workflow for building new features and handling complex changes. It ensures that all decisions are deliberate, grounded in evidence, and documented.
73
+
74
+ #### When to Use
75
+
76
+ You should use the full state machine for any significant piece of work.
77
+
78
+ **Example Invocations:**
79
+ * `"spex, let's build a new feature: user-to-user direct messaging."`
80
+ * `"I need to add support for Google authentication. Use spex for planning."`
81
+ * `"Plan and implement a dashboard for viewing analytics."`
82
+
83
+ #### How It Works
84
+
85
+ The full flow moves through a series of states, creating a dedicated folder at `.spex/<feature-name>/` to track all artifacts.
86
+
87
+ 1. **`INIT` → `RESEARCH_CODE` → `RESEARCH_MEMORY`:** The agent researches your current codebase and its own memory to gather all relevant context and identify potential conflicts.
88
+ 2. **`GENERATE_PLAN`:** Based on the research, it generates a detailed, step-by-step implementation plan.
89
+ 3. **`REVIEWING_PLAN` (Human Checkpoint):** You are presented with the plan for review. You have the final say and must approve it before work begins. This is where you make the key architectural and structural decisions.
90
+ 4. **`COMPILING_TASKS` → `EXECUTE`:** Once you approve the plan, the agent breaks it down into executable tasks and begins implementing them one by one.
91
+ 5. **`AUDITING`:** After each task, the agent audits the code changes against the approved plan to ensure there is no scope creep. **This step is mandatory and cannot be skipped.**
92
+ 6. **`COMPLETE`:** Once all tasks are executed and audited, the feature is complete. The agent proposes a final summary.
93
+
94
+ ### C. (See Section 4 for Knowledge Capture)
95
+ This functionality has been promoted to its own main section below.
96
+
97
+ ---
98
+
99
+ ## 3. `spex-reflect`: Improving Future Work
100
+
101
+ The `spex-reflect` skill is a powerful tool for continuous improvement. It analyzes completed features to extract learnings and propose reusable policies.
102
+
103
+ ### When to Use
104
+
105
+ You should use this skill **manually** after a feature has been marked as `COMPLETE` by the `spex` skill.
106
+
107
+ **Example Invocations:**
108
+ * `"spex reflect"`
109
+ * `"use spex to reflect on this feature"`
110
+ * `"analyze this feature and propose policies"`
111
+
112
+ ### How It Works
113
+
114
+ 1. **Gather Context:** It reviews the entire feature history: the plan, decisions made, audit results, and execution traces.
115
+ 2. **Analyze Learnings:** It identifies what went well (e.g., accurate planning) and what didn't (e.g., scope creep, conflicts).
116
+ 3. **Evaluate Decisions:** It assesses the architectural and structural decisions for quality and impact.
117
+ 4. **Propose Policies:** It identifies recurring patterns and proposes them as **Policies** (standing rules) to guide future development.
118
+ 5. **Persist:** Upon your approval, it saves these policies to Spex's memory, making the agent "smarter" for the next task.
119
+
120
+ ---
121
+
122
+ ## 4. Knowledge Capture: Teaching the Agent
123
+
124
+ Separate from feature development, you can use `spex` to "teach" the agent at any time. This captures Requirements, Decisions, and Policies directly into memory.
125
+
126
+ ### A. Learning from Conversation
127
+
128
+ Capture decisions or requirements that emerge dynamically during a chat.
129
+
130
+ **When to Use:**
131
+ * You just made a verbal decision in the chat (e.g., "Let's always use strict typing").
132
+ * You want to record a requirement found during debugging.
133
+
134
+ **Example Invocations:**
135
+ * `"spex memorize this conversation"`
136
+ * `"capture this decision"`
137
+ * `"spex, record that we decided to use red for all error states"`
138
+
139
+ **How It Works:**
140
+ The agent scans the recent conversation, extracts structured items (Requirements, Decisions), presents them for your review, and saves them.
141
+
142
+ ### B. Learning from Documentation
143
+
144
+ Teach the agent by having it read existing files.
145
+
146
+ **When to Use:**
147
+ * You have an `ARCHITECTURE.md` or `API_GUIDELINES.md` file.
148
+ * You want to ingest a project spec or requirements document.
149
+
150
+ **Example Invocations:**
151
+ * `"spex learn from docs/auth-flow.md"`
152
+ * `"teach spex via README.md"`
153
+ * `"analyze infrastructure.md for policies"`
154
+
155
+ **How It Works:**
156
+ 1. **Read:** The agent reads the specified file.
157
+ 2. **Extract:** It identifies User Requirements (UR), Functional Requirements (FR), Non-Functional Requirements (NFR), and technical Decisions.
158
+ 3. **Review:** It presents these items to you for confirmation.
159
+ 4. **Save:** Once approved, they are persisted to Spex memory, making that document's knowledge available to all future workflows.
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "spex-cli"
7
+ version = "0.1.0"
8
+ description = "CLI tool for managing requirements and decisions"
9
+ requires-python = ">=3.11"
10
+ readme = "README.md"
11
+ dependencies = [
12
+ "rich>=13.0",
13
+ "questionary>=2.0",
14
+ "ruff>=0.15.1",
15
+ ]
16
+
17
+ [project.scripts]
18
+ spex = "spex_cli:main"
19
+
20
+ [tool.hatch.build.targets.wheel]
21
+ packages = ["src/spex_cli"]
22
+
23
+ [project.optional-dependencies]
24
+ test = ["pytest>=8", "pytest-cov>=4.0"]
25
+ dev = [
26
+ "twine>=5.0.0",
27
+ "build>=1.0.0",
28
+ ]
29
+
30
+ [tool.pytest.ini_options]
31
+ testpaths = ["tests"]
32
+ python_files = ["test_*.py"]
33
+ python_classes = ["Test*"]
34
+ python_functions = ["test_*"]
35
+ addopts = ["-v", "--strict-markers", "--tb=short"]
36
+
37
+ [tool.ruff]
38
+ target-version = "py311"
39
+ line-length = 88
@@ -0,0 +1,82 @@
1
+ #!/bin/bash
2
+
3
+ # Exit immediately if a command exits with a non-zero status
4
+ set -e
5
+
6
+ # Define colors for output
7
+ GREEN='\033[0;32m'
8
+ YELLOW='\033[1;33m'
9
+ RED='\033[0;31m'
10
+ NC='\033[0m' # No Color
11
+
12
+ echo -e "${YELLOW}Starting deployment process for spex-cli...${NC}"
13
+
14
+ # Ensure we are in the project root
15
+ cd "$(dirname "$0")/.."
16
+
17
+ # 1. Check for uncommitted changes
18
+ if [[ -n $(git status -s) ]]; then
19
+ echo -e "${RED}Error: You have uncommitted changes. Please commit or stash them before deploying.${NC}"
20
+ exit 1
21
+ fi
22
+
23
+ # 2. Ensure build and twine are installed
24
+ echo -e "${YELLOW}Ensuring twine is available...${NC}"
25
+ if command -v uv &> /dev/null; then
26
+ # Use uv to run twine
27
+ RUN_TWINE="uv run twine"
28
+ BUILD_CMD="uv build"
29
+ else
30
+ echo -e "${YELLOW}uv not found, falling back to pip and python -m build...${NC}"
31
+ python3 -m pip install --upgrade build twine
32
+ RUN_TWINE="python3 -m twine"
33
+ BUILD_CMD="python3 -m build"
34
+ fi
35
+
36
+ # Detect local .pypirc
37
+ TWINE_OPTS=""
38
+ if [[ -f ".pypirc" ]]; then
39
+ echo -e "${YELLOW}Using local .pypirc file...${NC}"
40
+ TWINE_OPTS="--config-file .pypirc"
41
+ fi
42
+
43
+ # 3. Clean previous builds
44
+ echo -e "${YELLOW}Cleaning up previous builds...${NC}"
45
+ rm -rf dist/ build/ *.egg-info
46
+
47
+ # 4. Build the package
48
+ echo -e "${YELLOW}Building the package...${NC}"
49
+ $BUILD_CMD
50
+
51
+ # 5. Check the distribution packages
52
+ echo -e "${YELLOW}Running twine check...${NC}"
53
+ $RUN_TWINE check dist/*
54
+
55
+ # 6. Prompt for deployment target
56
+ echo -e "${GREEN}Build successful and verified!${NC}"
57
+ echo "Where would you like to upload?"
58
+ echo "1) TestPyPI (recommended for testing)"
59
+ echo "2) PyPI (production)"
60
+ echo "3) Exit"
61
+ read -p "Enter choice [1-3]: " choice
62
+
63
+ case $choice in
64
+ 1)
65
+ echo -e "${YELLOW}Uploading to TestPyPI...${NC}"
66
+ $RUN_TWINE upload $TWINE_OPTS --repository testpypi dist/*
67
+ ;;
68
+ 2)
69
+ echo -e "${YELLOW}Uploading to PyPI...${NC}"
70
+ $RUN_TWINE upload $TWINE_OPTS dist/*
71
+ ;;
72
+ 3)
73
+ echo -e "${YELLOW}Exiting without upload.${NC}"
74
+ exit 0
75
+ ;;
76
+ *)
77
+ echo -e "${RED}Invalid choice. Exiting.${NC}"
78
+ exit 1
79
+ ;;
80
+ esac
81
+
82
+ echo -e "${GREEN}Deployment complete!${NC}"
@@ -0,0 +1,69 @@
1
+ from rich.align import Align
2
+ from rich.console import Console
3
+ from rich.panel import Panel
4
+ from rich.text import Text
5
+
6
+ from spex_cli.spex import main as _main
7
+
8
+ _BANNER_LINES = [
9
+ " ███████╗██████╗ ███████╗██╗ ██╗",
10
+ " ██╔════╝██╔══██╗██╔════╝╚██╗██╔╝",
11
+ " ███████╗██████╔╝█████╗ ╚███╔╝ ",
12
+ " ╚════██║██╔═══╝ ██╔══╝ ██╔██╗ ",
13
+ " ███████║██║ ███████╗██╔╝ ██╗",
14
+ " ╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝",
15
+ ]
16
+
17
+ _ROW_COLORS = [
18
+ "#F97316",
19
+ "#F97316",
20
+ "#FBBF24",
21
+ "#FBBF24",
22
+ "#EC4899",
23
+ "#EC4899",
24
+ ]
25
+
26
+
27
+ def print_banner() -> None:
28
+ console = Console(stderr=True)
29
+
30
+ art = Text(justify="center")
31
+ for i, (line, color) in enumerate(zip(_BANNER_LINES, _ROW_COLORS)):
32
+ art.append(line, style=f"bold {color}")
33
+ if i < len(_BANNER_LINES) - 1:
34
+ art.append("\n")
35
+
36
+ subtitle = Text(justify="center")
37
+ subtitle.append("Autonomous Engineering experience", style="bold #8B5CF6")
38
+ subtitle.append(" · ", style="dim")
39
+ subtitle.append("v0.1.0", style="#FBBF24")
40
+
41
+ console.print(
42
+ Panel(
43
+ Align.center(Text.assemble(art, "\n\n", subtitle)),
44
+ border_style="#8B5CF6",
45
+ padding=(1, 4),
46
+ )
47
+ )
48
+
49
+
50
+ _BANNER_COMMANDS = frozenset({"healthcheck", "enable", "disable"})
51
+
52
+
53
+ def _should_show_banner() -> bool:
54
+ import sys
55
+ args = sys.argv[1:]
56
+ if not args:
57
+ return True
58
+ first = args[0]
59
+ if first in ("-h", "--help"):
60
+ return True
61
+ if first in _BANNER_COMMANDS:
62
+ return True
63
+ return False
64
+
65
+
66
+ def main() -> None:
67
+ if _should_show_banner():
68
+ print_banner()
69
+ _main()
@@ -0,0 +1,130 @@
1
+ import json
2
+ from rich.console import Console
3
+ from rich.table import Table
4
+ from rich.text import Text
5
+
6
+ _console = Console()
7
+
8
+ _COMMANDS = [
9
+ ("Developers", [
10
+ ("enable", [], "Set up spex in the current repository"),
11
+ ("disable", [], "Remove spex git hook and revert agent settings"),
12
+ ("healthcheck", [], "Audit hooks and memory integrity"),
13
+ ]),
14
+ ("Memory", [
15
+ ("requirement", ["add", "deprecate"], "Track functional and non-functional requirements"),
16
+ ("decision", ["add", "deprecate"], "Record technical decisions with rationale and impact"),
17
+ ("policy", ["add", "deprecate"], "Project-wide policies and guidelines"),
18
+ ("app", ["add", "update"], "Register applications and libraries"),
19
+ ("plan", ["add", "update-status", "deprecate"], "Feature planning lifecycle"),
20
+ ]),
21
+ ("System", [
22
+ ("trace", ["add"], "Link commits to decisions via git trailers"),
23
+ ("blame", ["<file>[:<lines>]"], "Find decisions and requirements for a file or line range"),
24
+ ("validate-and-route", ["--feature-name", "--target-state"], "Enforce state machine transitions"),
25
+ ]),
26
+ ]
27
+
28
+ _SUBCOMMANDS = {
29
+ "requirement": [
30
+ ("add", "Add a new requirement to memory"),
31
+ ("deprecate", "Deprecate an existing requirement"),
32
+ ],
33
+ "decision": [
34
+ ("add", "Add a new technical decision"),
35
+ ("deprecate", "Mark a decision as obsolete"),
36
+ ],
37
+ "policy": [
38
+ ("add", "Add a new project-wide policy or guideline"),
39
+ ("deprecate", "Deprecate an existing policy"),
40
+ ],
41
+ "app": [
42
+ ("add", "Register a new application or library"),
43
+ ("update", "Update app or library details"),
44
+ ],
45
+ "plan": [
46
+ ("add", "Create a new feature plan"),
47
+ ("update-status", "Update the current status of a plan"),
48
+ ("deprecate", "Abandon a plan"),
49
+ ],
50
+ "trace": [
51
+ ("add", "Link a commit hash to a decision"),
52
+ ],
53
+ }
54
+
55
+
56
+ def print_help() -> None:
57
+ _console.print()
58
+ _console.print(
59
+ " [bold]Usage:[/bold] [bold #F97316]spex[/bold #F97316] "
60
+ "[#FBBF24]<command>[/#FBBF24] [dim][options][/dim]"
61
+ )
62
+ _console.print()
63
+
64
+ for section, commands in _COMMANDS:
65
+ _console.rule(f"[bold #8B5CF6] {section} [/bold #8B5CF6]", style="dim #8B5CF6")
66
+ _console.print()
67
+
68
+ table = Table(box=None, padding=(0, 2, 0, 4), show_header=False, expand=False)
69
+ table.add_column("cmd", style="bold #F97316", no_wrap=True)
70
+ table.add_column("actions", no_wrap=True)
71
+ table.add_column("desc", style="dim", no_wrap=False)
72
+
73
+ for cmd, actions, desc in commands:
74
+ action_text = Text()
75
+ for i, action in enumerate(actions):
76
+ if i > 0:
77
+ action_text.append(" ", style="dim")
78
+ action_text.append(action, style="#FBBF24")
79
+ table.add_row(cmd, action_text, desc)
80
+
81
+ _console.print(table)
82
+ _console.print()
83
+
84
+ _console.print(
85
+ " [dim]Run [/dim][bold #F97316]spex[/bold #F97316]"
86
+ " [dim]<command> --help for more information.[/dim]"
87
+ )
88
+ _console.print()
89
+
90
+
91
+ def print_subcommand_help(command: str) -> None:
92
+ actions = _SUBCOMMANDS.get(command, [])
93
+ _console.print()
94
+ _console.rule(
95
+ f"[bold #8B5CF6] spex {command} [/bold #8B5CF6]",
96
+ style="dim #8B5CF6",
97
+ )
98
+ _console.print()
99
+
100
+ table = Table(box=None, padding=(0, 2, 0, 4), show_header=False, expand=False)
101
+ table.add_column("action", style="bold #FBBF24", no_wrap=True)
102
+ table.add_column("desc", style="dim", no_wrap=True)
103
+
104
+ for action, desc in actions:
105
+ table.add_row(action, desc)
106
+
107
+ _console.print(table)
108
+ _console.print()
109
+ _console.print(
110
+ f" [dim]Run [/dim][bold #F97316]spex {command}[/bold #F97316]"
111
+ " [dim]<action> --help for details.[/dim]"
112
+ )
113
+ _console.print()
114
+
115
+
116
+ def print_help_json() -> None:
117
+ output = {
118
+ "usage": "spex <command> [options]",
119
+ "sections": [
120
+ {
121
+ "section": section,
122
+ "commands": [
123
+ {"name": cmd, "actions": actions, "description": desc}
124
+ for cmd, actions, desc in commands
125
+ ],
126
+ }
127
+ for section, commands in _COMMANDS
128
+ ],
129
+ }
130
+ print(json.dumps(output, indent=2))
@@ -0,0 +1,33 @@
1
+ AGENT_CONFIG = {
2
+ "claude": {
3
+ "name": "Claude Code",
4
+ "folder": ".claude/",
5
+ "settings_file": "claude_settings/settings.json",
6
+ },
7
+ "gemini": {
8
+ "name": "Gemini CLI",
9
+ "folder": ".gemini/",
10
+ "settings_file": "claude_settings/settings.json"
11
+ },
12
+ "cursor-agent": {
13
+ "name": "Cursor",
14
+ "folder": ".cursor/",
15
+ "settings_file": "claude_settings/settings.json"
16
+ },
17
+ "opencode": {
18
+ "name": "opencode",
19
+ "folder": ".opencode/"
20
+ },
21
+ "codex": {
22
+ "name": "Codex CLI",
23
+ "folder": ".codex/"
24
+ },
25
+ "agy": {
26
+ "name": "Antigravity",
27
+ "folder": ".agent/"
28
+ },
29
+ "copilot": {
30
+ "name": "GitHub Copilot",
31
+ "folder": ".github/"
32
+ }
33
+ }