vibe-state-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.
- vibe_state_cli-0.1.0/.gitignore +45 -0
- vibe_state_cli-0.1.0/LICENSE +21 -0
- vibe_state_cli-0.1.0/PKG-INFO +129 -0
- vibe_state_cli-0.1.0/README.md +88 -0
- vibe_state_cli-0.1.0/pyproject.toml +82 -0
- vibe_state_cli-0.1.0/src/vibe_state/__init__.py +3 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/__init__.py +0 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/agents_md.py +39 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/antigravity.py +49 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/base.py +201 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/claude.py +68 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/cline.py +45 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/copilot.py +58 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/cursor.py +49 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/registry.py +60 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/roo.py +30 -0
- vibe_state_cli-0.1.0/src/vibe_state/adapters/windsurf.py +53 -0
- vibe_state_cli-0.1.0/src/vibe_state/cli.py +47 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/__init__.py +0 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/_helpers.py +165 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/cmd_adapt.py +133 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/cmd_init.py +141 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/cmd_start.py +121 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/cmd_status.py +59 -0
- vibe_state_cli-0.1.0/src/vibe_state/commands/cmd_sync.py +150 -0
- vibe_state_cli-0.1.0/src/vibe_state/config.py +108 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/__init__.py +0 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/compactor.py +218 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/git_ops.py +172 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/lifecycle.py +85 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/scanner.py +106 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/state.py +172 -0
- vibe_state_cli-0.1.0/src/vibe_state/core/templates.py +83 -0
- vibe_state_cli-0.1.0/src/vibe_state/py.typed +0 -0
- vibe_state_cli-0.1.0/src/vibe_state/safety.py +56 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/architecture.md.j2 +20 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/archive.md.j2 +3 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/current.md.j2 +9 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/experiments.md.j2 +6 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/standards.md.j2 +16 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/state/tasks.md.j2 +3 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/vibe.md.j2 +52 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/architecture.md.j2 +20 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/archive.md.j2 +3 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/current.md.j2 +9 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/experiments.md.j2 +6 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/standards.md.j2 +16 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/state/tasks.md.j2 +3 -0
- vibe_state_cli-0.1.0/src/vibe_state/templates/zh-TW/vibe.md.j2 +52 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
*~
|
|
23
|
+
|
|
24
|
+
# OS
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
27
|
+
|
|
28
|
+
# Testing
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.coverage
|
|
31
|
+
htmlcov/
|
|
32
|
+
.mypy_cache/
|
|
33
|
+
|
|
34
|
+
# Environment
|
|
35
|
+
.env
|
|
36
|
+
.env.local
|
|
37
|
+
|
|
38
|
+
# Distribution
|
|
39
|
+
*.whl
|
|
40
|
+
*.tar.gz
|
|
41
|
+
|
|
42
|
+
# vibe-state-cli development
|
|
43
|
+
# Keep .vibe/ tracked for dogfooding, but ignore backups/snapshots
|
|
44
|
+
.vibe/backups/
|
|
45
|
+
.vibe/snapshots/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vibe-state-cli contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vibe-state-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Model-agnostic AI-human collaboration state management CLI
|
|
5
|
+
Project-URL: Homepage, https://github.com/vibe-state-cli/vibe-state-cli
|
|
6
|
+
Project-URL: Documentation, https://vibe-state-cli.github.io/
|
|
7
|
+
Project-URL: Repository, https://github.com/vibe-state-cli/vibe-state-cli
|
|
8
|
+
Project-URL: Issues, https://github.com/vibe-state-cli/vibe-state-cli/issues
|
|
9
|
+
Author: vibe-state-cli contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,cli,developer-tools,state-management,vibe
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: jinja2>=3.1.0
|
|
26
|
+
Requires-Dist: markdown-it-py>=3.0.0
|
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
|
28
|
+
Requires-Dist: rich>=13.0.0
|
|
29
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
30
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
31
|
+
Requires-Dist: typer>=0.9.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
38
|
+
Provides-Extra: mcp
|
|
39
|
+
Requires-Dist: mcp>=1.27.0; extra == 'mcp'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# vibe-state-cli
|
|
43
|
+
|
|
44
|
+
[English](README.md) | [繁體中文](docs/zh-TW/README.md)
|
|
45
|
+
|
|
46
|
+
**Model-agnostic AI-human collaboration state management CLI.**
|
|
47
|
+
|
|
48
|
+
Let any AI model — Claude, GPT, Gemini, or local models — instantly sync with your project's context by reading a single `.vibe/` directory.
|
|
49
|
+
|
|
50
|
+
## Why vibe?
|
|
51
|
+
|
|
52
|
+
| Problem | How vibe solves it |
|
|
53
|
+
|---------|-------------------|
|
|
54
|
+
| AI loses memory every session | `.vibe/state/` persists across sessions and tools |
|
|
55
|
+
| Switching AI tools = starting over | 8 adapters generate each tool's native config from one source |
|
|
56
|
+
| CLAUDE.md grows forever, wastes tokens | `vibe sync --compact` auto-archives, keeps state lean (~684 tokens) |
|
|
57
|
+
| Manual copy-paste of context prompts | `vibe init` scans your project and generates everything |
|
|
58
|
+
| No structured handoff between sessions | `vibe sync` appends git state + C.L.E.A.R. review checklist |
|
|
59
|
+
|
|
60
|
+
Works **100% offline**. No API keys, no telemetry, no network calls.
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pipx install vibe-state-cli
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd my-project
|
|
72
|
+
|
|
73
|
+
vibe init # Initialize .vibe/ (auto-detects language, framework, AI tools)
|
|
74
|
+
vibe start # Daily start — load state, git check, auto-compact
|
|
75
|
+
vibe sync # Daily close — append git status, C.L.E.A.R. review
|
|
76
|
+
vibe sync --compact # Archive completed tasks, compress state files
|
|
77
|
+
vibe sync --close # End project — final sync + retrospective
|
|
78
|
+
vibe status # Check project state (anytime)
|
|
79
|
+
vibe adapt --list # See which AI tool adapters are enabled
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 5 Commands
|
|
83
|
+
|
|
84
|
+
| Command | When | What it does |
|
|
85
|
+
|---------|------|-------------|
|
|
86
|
+
| `vibe init` | Once | Scan project, generate `.vibe/`, detect AI tools, emit adapter files |
|
|
87
|
+
| `vibe start` | Daily | Load state, validate vs git, auto-compact if needed, Rich summary |
|
|
88
|
+
| `vibe sync` | Daily | Append git status to state, C.L.E.A.R. checklist |
|
|
89
|
+
| `vibe status` | Anytime | Show lifecycle, tasks, file sizes |
|
|
90
|
+
| `vibe adapt` | As needed | `--add`/`--remove`/`--list`/`--sync` adapter files |
|
|
91
|
+
|
|
92
|
+
### Flags
|
|
93
|
+
|
|
94
|
+
- `vibe init --lang zh-TW` — Traditional Chinese templates
|
|
95
|
+
- `vibe init --force` — Reinitialize or reopen a closed project
|
|
96
|
+
- `vibe sync --compact` — Run memory compaction after sync
|
|
97
|
+
- `vibe sync --close` — Close project with retrospective
|
|
98
|
+
- `vibe adapt --remove cursor --dry-run` — Preview before deleting
|
|
99
|
+
- `vibe adapt --remove cursor --confirm` — Delete with backup
|
|
100
|
+
|
|
101
|
+
## Supported AI Tools
|
|
102
|
+
|
|
103
|
+
| Tool | Generated Config | Auto-detected by |
|
|
104
|
+
|------|-----------------|------------------|
|
|
105
|
+
| AGENTS.md | `AGENTS.md` | `AGENTS.md` exists |
|
|
106
|
+
| Claude Code | `CLAUDE.md` + `.claude/rules/` | `.claude/` directory |
|
|
107
|
+
| Antigravity / Gemini | `GEMINI.md` | `GEMINI.md` or `.gemini/` |
|
|
108
|
+
| Cursor | `.cursor/rules/*.mdc` | `.cursor/` directory |
|
|
109
|
+
| GitHub Copilot | `.github/copilot-instructions.md` | existing copilot config |
|
|
110
|
+
| Windsurf | `.windsurf/rules/*.md` | `.windsurf/` directory |
|
|
111
|
+
| Cline | `.clinerules/*.md` | `.clinerules/` directory |
|
|
112
|
+
| Roo Code | `.roo/rules/*.md` | `.roo/` directory |
|
|
113
|
+
|
|
114
|
+
Only detected tools get adapter files generated. No bloat.
|
|
115
|
+
|
|
116
|
+
## Autoresearch Integration
|
|
117
|
+
|
|
118
|
+
Supports [autoresearch](https://github.com/uditgoenka/autoresearch) experiment loops. `vibe sync` auto-detects experiment commits and records results to `state/experiments.md`.
|
|
119
|
+
|
|
120
|
+
## Safety
|
|
121
|
+
|
|
122
|
+
- `vibe adapt --remove` defaults to **dry-run** — requires `--confirm` to delete
|
|
123
|
+
- Snapshots saved on every emit for diff detection
|
|
124
|
+
- Backups kept (last 3) before any deletion
|
|
125
|
+
- User-modified files trigger warnings before overwrite
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# vibe-state-cli
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [繁體中文](docs/zh-TW/README.md)
|
|
4
|
+
|
|
5
|
+
**Model-agnostic AI-human collaboration state management CLI.**
|
|
6
|
+
|
|
7
|
+
Let any AI model — Claude, GPT, Gemini, or local models — instantly sync with your project's context by reading a single `.vibe/` directory.
|
|
8
|
+
|
|
9
|
+
## Why vibe?
|
|
10
|
+
|
|
11
|
+
| Problem | How vibe solves it |
|
|
12
|
+
|---------|-------------------|
|
|
13
|
+
| AI loses memory every session | `.vibe/state/` persists across sessions and tools |
|
|
14
|
+
| Switching AI tools = starting over | 8 adapters generate each tool's native config from one source |
|
|
15
|
+
| CLAUDE.md grows forever, wastes tokens | `vibe sync --compact` auto-archives, keeps state lean (~684 tokens) |
|
|
16
|
+
| Manual copy-paste of context prompts | `vibe init` scans your project and generates everything |
|
|
17
|
+
| No structured handoff between sessions | `vibe sync` appends git state + C.L.E.A.R. review checklist |
|
|
18
|
+
|
|
19
|
+
Works **100% offline**. No API keys, no telemetry, no network calls.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pipx install vibe-state-cli
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd my-project
|
|
31
|
+
|
|
32
|
+
vibe init # Initialize .vibe/ (auto-detects language, framework, AI tools)
|
|
33
|
+
vibe start # Daily start — load state, git check, auto-compact
|
|
34
|
+
vibe sync # Daily close — append git status, C.L.E.A.R. review
|
|
35
|
+
vibe sync --compact # Archive completed tasks, compress state files
|
|
36
|
+
vibe sync --close # End project — final sync + retrospective
|
|
37
|
+
vibe status # Check project state (anytime)
|
|
38
|
+
vibe adapt --list # See which AI tool adapters are enabled
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 5 Commands
|
|
42
|
+
|
|
43
|
+
| Command | When | What it does |
|
|
44
|
+
|---------|------|-------------|
|
|
45
|
+
| `vibe init` | Once | Scan project, generate `.vibe/`, detect AI tools, emit adapter files |
|
|
46
|
+
| `vibe start` | Daily | Load state, validate vs git, auto-compact if needed, Rich summary |
|
|
47
|
+
| `vibe sync` | Daily | Append git status to state, C.L.E.A.R. checklist |
|
|
48
|
+
| `vibe status` | Anytime | Show lifecycle, tasks, file sizes |
|
|
49
|
+
| `vibe adapt` | As needed | `--add`/`--remove`/`--list`/`--sync` adapter files |
|
|
50
|
+
|
|
51
|
+
### Flags
|
|
52
|
+
|
|
53
|
+
- `vibe init --lang zh-TW` — Traditional Chinese templates
|
|
54
|
+
- `vibe init --force` — Reinitialize or reopen a closed project
|
|
55
|
+
- `vibe sync --compact` — Run memory compaction after sync
|
|
56
|
+
- `vibe sync --close` — Close project with retrospective
|
|
57
|
+
- `vibe adapt --remove cursor --dry-run` — Preview before deleting
|
|
58
|
+
- `vibe adapt --remove cursor --confirm` — Delete with backup
|
|
59
|
+
|
|
60
|
+
## Supported AI Tools
|
|
61
|
+
|
|
62
|
+
| Tool | Generated Config | Auto-detected by |
|
|
63
|
+
|------|-----------------|------------------|
|
|
64
|
+
| AGENTS.md | `AGENTS.md` | `AGENTS.md` exists |
|
|
65
|
+
| Claude Code | `CLAUDE.md` + `.claude/rules/` | `.claude/` directory |
|
|
66
|
+
| Antigravity / Gemini | `GEMINI.md` | `GEMINI.md` or `.gemini/` |
|
|
67
|
+
| Cursor | `.cursor/rules/*.mdc` | `.cursor/` directory |
|
|
68
|
+
| GitHub Copilot | `.github/copilot-instructions.md` | existing copilot config |
|
|
69
|
+
| Windsurf | `.windsurf/rules/*.md` | `.windsurf/` directory |
|
|
70
|
+
| Cline | `.clinerules/*.md` | `.clinerules/` directory |
|
|
71
|
+
| Roo Code | `.roo/rules/*.md` | `.roo/` directory |
|
|
72
|
+
|
|
73
|
+
Only detected tools get adapter files generated. No bloat.
|
|
74
|
+
|
|
75
|
+
## Autoresearch Integration
|
|
76
|
+
|
|
77
|
+
Supports [autoresearch](https://github.com/uditgoenka/autoresearch) experiment loops. `vibe sync` auto-detects experiment commits and records results to `state/experiments.md`.
|
|
78
|
+
|
|
79
|
+
## Safety
|
|
80
|
+
|
|
81
|
+
- `vibe adapt --remove` defaults to **dry-run** — requires `--confirm` to delete
|
|
82
|
+
- Snapshots saved on every emit for diff detection
|
|
83
|
+
- Backups kept (last 3) before any deletion
|
|
84
|
+
- User-modified files trigger warnings before overwrite
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vibe-state-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Model-agnostic AI-human collaboration state management CLI"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "vibe-state-cli contributors" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "cli", "state-management", "developer-tools", "vibe"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Software Development :: Build Tools",
|
|
27
|
+
"Topic :: Software Development :: Libraries",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"typer>=0.9.0",
|
|
31
|
+
"rich>=13.0.0",
|
|
32
|
+
"jinja2>=3.1.0",
|
|
33
|
+
"markdown-it-py>=3.0.0",
|
|
34
|
+
"pydantic>=2.0.0",
|
|
35
|
+
"tomli>=2.0.0; python_version < '3.11'",
|
|
36
|
+
"tomli-w>=1.0.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=8.0.0",
|
|
42
|
+
"pytest-cov>=5.0.0",
|
|
43
|
+
"ruff>=0.4.0",
|
|
44
|
+
"mypy>=1.10.0",
|
|
45
|
+
"pre-commit>=3.0.0",
|
|
46
|
+
]
|
|
47
|
+
mcp = [
|
|
48
|
+
"mcp>=1.27.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
vibe = "vibe_state.cli:app"
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://github.com/vibe-state-cli/vibe-state-cli"
|
|
56
|
+
Documentation = "https://vibe-state-cli.github.io/"
|
|
57
|
+
Repository = "https://github.com/vibe-state-cli/vibe-state-cli"
|
|
58
|
+
Issues = "https://github.com/vibe-state-cli/vibe-state-cli/issues"
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.targets.sdist]
|
|
61
|
+
include = ["src/vibe_state"]
|
|
62
|
+
|
|
63
|
+
[tool.hatch.build.targets.wheel]
|
|
64
|
+
packages = ["src/vibe_state"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff]
|
|
67
|
+
target-version = "py310"
|
|
68
|
+
line-length = 100
|
|
69
|
+
src = ["src"]
|
|
70
|
+
|
|
71
|
+
[tool.ruff.lint]
|
|
72
|
+
select = ["E", "F", "W", "I", "UP", "B", "SIM"]
|
|
73
|
+
|
|
74
|
+
[tool.mypy]
|
|
75
|
+
python_version = "3.10"
|
|
76
|
+
strict = true
|
|
77
|
+
warn_return_any = true
|
|
78
|
+
warn_unused_configs = true
|
|
79
|
+
|
|
80
|
+
[tool.pytest.ini_options]
|
|
81
|
+
testpaths = ["tests"]
|
|
82
|
+
addopts = "-v --tb=short"
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""AGENTS.md adapter — Linux Foundation / AAIF universal standard."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from vibe_state.adapters.base import AdapterBase, AdapterContext
|
|
8
|
+
from vibe_state.adapters.registry import register_adapter
|
|
9
|
+
|
|
10
|
+
MAX_SIZE_BYTES = 32 * 1024
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@register_adapter
|
|
14
|
+
class AgentsMdAdapter(AdapterBase):
|
|
15
|
+
name = "agents_md"
|
|
16
|
+
REQUIRED_FIELDS: set[str] = set()
|
|
17
|
+
|
|
18
|
+
def detect(self, project_root: Path) -> bool:
|
|
19
|
+
return (project_root / "AGENTS.md").exists()
|
|
20
|
+
|
|
21
|
+
def emit(self, ctx: AdapterContext) -> list[Path]:
|
|
22
|
+
lines = [
|
|
23
|
+
f"# AGENTS.md — {ctx.project_name}",
|
|
24
|
+
"",
|
|
25
|
+
"## Project",
|
|
26
|
+
"",
|
|
27
|
+
]
|
|
28
|
+
lines += self._build_common_body(ctx)
|
|
29
|
+
content = "\n".join(lines)
|
|
30
|
+
if not self.validate(content):
|
|
31
|
+
self._warn_validation("AGENTS.md (>32KiB)")
|
|
32
|
+
return [self._write_file(ctx.project_root / "AGENTS.md", content)]
|
|
33
|
+
|
|
34
|
+
def clean(self, project_root: Path) -> list[Path]:
|
|
35
|
+
p = project_root / "AGENTS.md"
|
|
36
|
+
return [p] if p.exists() else []
|
|
37
|
+
|
|
38
|
+
def validate(self, output: str) -> bool:
|
|
39
|
+
return len(output.encode("utf-8")) <= MAX_SIZE_BYTES
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Antigravity / Gemini CLI adapter — GEMINI.md (plain Markdown, no frontmatter)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from vibe_state.adapters.base import AdapterBase, AdapterContext
|
|
8
|
+
from vibe_state.adapters.registry import register_adapter
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@register_adapter
|
|
12
|
+
class AntigravityAdapter(AdapterBase):
|
|
13
|
+
name = "antigravity"
|
|
14
|
+
REQUIRED_FIELDS: set[str] = set() # No frontmatter for GEMINI.md
|
|
15
|
+
|
|
16
|
+
def detect(self, project_root: Path) -> bool:
|
|
17
|
+
return (project_root / "GEMINI.md").exists()
|
|
18
|
+
|
|
19
|
+
def emit(self, ctx: AdapterContext) -> list[Path]:
|
|
20
|
+
lines = [f"# GEMINI.md — {ctx.project_name}", ""]
|
|
21
|
+
|
|
22
|
+
if "agents_md" in ctx.enabled_adapters:
|
|
23
|
+
# Import AGENTS.md to avoid duplication (same pattern as Claude adapter)
|
|
24
|
+
lines += [
|
|
25
|
+
"@AGENTS.md",
|
|
26
|
+
"",
|
|
27
|
+
"## Antigravity-Specific",
|
|
28
|
+
"",
|
|
29
|
+
]
|
|
30
|
+
else:
|
|
31
|
+
# Self-contained: include full project info
|
|
32
|
+
lines += ["## Project", ""]
|
|
33
|
+
lines += self._build_common_body(ctx)
|
|
34
|
+
|
|
35
|
+
lines += [
|
|
36
|
+
"## Vibe Workflow",
|
|
37
|
+
"",
|
|
38
|
+
"Read `.vibe/VIBE.md` for the full protocol.",
|
|
39
|
+
"**Checkpoint**: After each task, mark `[x]` in `state/tasks.md`"
|
|
40
|
+
" and append to `state/current.md`.",
|
|
41
|
+
"**Reality-First**: When memory conflicts with git, trust git.",
|
|
42
|
+
"",
|
|
43
|
+
]
|
|
44
|
+
content = "\n".join(lines)
|
|
45
|
+
return [self._write_file(ctx.project_root / "GEMINI.md", content)]
|
|
46
|
+
|
|
47
|
+
def clean(self, project_root: Path) -> list[Path]:
|
|
48
|
+
p = project_root / "GEMINI.md"
|
|
49
|
+
return [p] if p.exists() else []
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""Base adapter interface for all AI/IDE tool adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class AdapterContext:
|
|
12
|
+
"""Context passed to adapters for file generation."""
|
|
13
|
+
|
|
14
|
+
project_root: Path
|
|
15
|
+
vibe_dir: Path
|
|
16
|
+
constitution: str # VIBE.md content
|
|
17
|
+
standards: str # state/standards.md content
|
|
18
|
+
architecture: str # state/architecture.md content
|
|
19
|
+
languages: list[str] = field(default_factory=list)
|
|
20
|
+
frameworks: list[str] = field(default_factory=list)
|
|
21
|
+
project_name: str = ""
|
|
22
|
+
enabled_adapters: list[str] = field(default_factory=list)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _sanitize(value: str) -> str:
|
|
26
|
+
"""Strip newlines, #, quotes, and control chars from user-controlled strings."""
|
|
27
|
+
return "".join(c for c in value if c.isprintable() and c not in '\n\r#"\'`')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Patterns that indicate malicious injection in standards/state files
|
|
31
|
+
_SUSPICIOUS_PATTERNS = [
|
|
32
|
+
"eval(",
|
|
33
|
+
"exec(",
|
|
34
|
+
"system(",
|
|
35
|
+
"import os",
|
|
36
|
+
"import subprocess",
|
|
37
|
+
"__import__",
|
|
38
|
+
"curl ",
|
|
39
|
+
"wget ",
|
|
40
|
+
"rm -rf",
|
|
41
|
+
"ignore all",
|
|
42
|
+
"ignore previous",
|
|
43
|
+
"disregard",
|
|
44
|
+
"override all",
|
|
45
|
+
"new rule",
|
|
46
|
+
"send all",
|
|
47
|
+
"exfiltrate",
|
|
48
|
+
"http://",
|
|
49
|
+
"https://",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _is_suspicious_instruction(text: str) -> bool:
|
|
54
|
+
"""Detect potentially malicious instructions in state file content."""
|
|
55
|
+
lower = text.lower()
|
|
56
|
+
return any(pattern in lower for pattern in _SUSPICIOUS_PATTERNS)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def build_adapter_context(project_root: Path) -> AdapterContext:
|
|
60
|
+
"""Build AdapterContext from .vibe/ config + state files."""
|
|
61
|
+
vibe_dir = project_root / ".vibe"
|
|
62
|
+
|
|
63
|
+
def _read(rel: str) -> str:
|
|
64
|
+
p = vibe_dir / rel
|
|
65
|
+
return p.read_text(encoding="utf-8") if p.exists() else ""
|
|
66
|
+
|
|
67
|
+
from vibe_state.config import load_config
|
|
68
|
+
|
|
69
|
+
config = load_config(vibe_dir)
|
|
70
|
+
|
|
71
|
+
# Parse languages/frameworks from architecture.md
|
|
72
|
+
languages: list[str] = []
|
|
73
|
+
frameworks: list[str] = []
|
|
74
|
+
arch = _read("state/architecture.md")
|
|
75
|
+
for line in arch.splitlines():
|
|
76
|
+
if line.strip().startswith("- Language:"):
|
|
77
|
+
lang_val = line.split(":", 1)[1].strip()
|
|
78
|
+
if lang_val:
|
|
79
|
+
languages.append(lang_val)
|
|
80
|
+
if line.strip().startswith("- Framework:"):
|
|
81
|
+
fw_val = line.split(":", 1)[1].strip()
|
|
82
|
+
if fw_val:
|
|
83
|
+
frameworks.append(fw_val)
|
|
84
|
+
|
|
85
|
+
return AdapterContext(
|
|
86
|
+
project_root=project_root,
|
|
87
|
+
vibe_dir=vibe_dir,
|
|
88
|
+
constitution=_read("VIBE.md"),
|
|
89
|
+
standards=_read("state/standards.md"),
|
|
90
|
+
architecture=_read("state/architecture.md"),
|
|
91
|
+
languages=[_sanitize(lang) for lang in languages],
|
|
92
|
+
frameworks=[_sanitize(fw) for fw in frameworks],
|
|
93
|
+
project_name=_sanitize(project_root.name),
|
|
94
|
+
enabled_adapters=config.adapters.enabled,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AdapterBase(ABC):
|
|
99
|
+
"""Abstract base class for all adapters."""
|
|
100
|
+
|
|
101
|
+
name: str = ""
|
|
102
|
+
REQUIRED_FIELDS: set[str] = set()
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def detect(self, project_root: Path) -> bool:
|
|
106
|
+
"""Detect if this tool's config already exists in the project."""
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
def emit(self, ctx: AdapterContext) -> list[Path]:
|
|
110
|
+
"""Generate config files for this tool. Returns list of created file paths."""
|
|
111
|
+
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def clean(self, project_root: Path) -> list[Path]:
|
|
114
|
+
"""Return list of files that would be removed for this adapter."""
|
|
115
|
+
|
|
116
|
+
def validate(self, output: str) -> bool:
|
|
117
|
+
"""Validate emitted file content. Override for frontmatter checks."""
|
|
118
|
+
return True
|
|
119
|
+
|
|
120
|
+
def _write_file(self, path: Path, content: str) -> Path:
|
|
121
|
+
"""Write content to file with integrity marker (markdown only)."""
|
|
122
|
+
import hashlib
|
|
123
|
+
|
|
124
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
125
|
+
# Add integrity marker only to markdown files (not JSON, TOML, etc.)
|
|
126
|
+
if path.suffix in (".md", ".mdc"):
|
|
127
|
+
content_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()[:12]
|
|
128
|
+
content = content.rstrip() + f"\n\n<!-- vibe-state-cli:integrity:{content_hash} -->\n"
|
|
129
|
+
path.write_text(content, encoding="utf-8", newline="\n")
|
|
130
|
+
return path
|
|
131
|
+
|
|
132
|
+
def _build_common_body(
|
|
133
|
+
self, ctx: AdapterContext, *, slim: bool = False
|
|
134
|
+
) -> list[str]:
|
|
135
|
+
"""Build the common project info + standards + security block.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
slim: If True, emit only the session-start directive (for when
|
|
139
|
+
AGENTS.md is also enabled and already carries the full body).
|
|
140
|
+
"""
|
|
141
|
+
lines: list[str] = []
|
|
142
|
+
|
|
143
|
+
if slim:
|
|
144
|
+
# Minimal: just point to AGENTS.md and .vibe/ for details
|
|
145
|
+
lines += [
|
|
146
|
+
"See AGENTS.md for project standards and security rules.",
|
|
147
|
+
"",
|
|
148
|
+
]
|
|
149
|
+
else:
|
|
150
|
+
if ctx.languages:
|
|
151
|
+
lines.append(f"- Languages: {', '.join(ctx.languages)}")
|
|
152
|
+
if ctx.frameworks:
|
|
153
|
+
lines.append(f"- Frameworks: {', '.join(ctx.frameworks)}")
|
|
154
|
+
lines.append("")
|
|
155
|
+
|
|
156
|
+
# Pull standards with injection detection
|
|
157
|
+
has_security = False
|
|
158
|
+
if ctx.standards:
|
|
159
|
+
for line in ctx.standards.splitlines():
|
|
160
|
+
stripped = line.strip()
|
|
161
|
+
if stripped.startswith("- ") and not stripped.startswith("- ("):
|
|
162
|
+
# Block suspicious instructions from propagating
|
|
163
|
+
lower = stripped.lower()
|
|
164
|
+
if _is_suspicious_instruction(lower):
|
|
165
|
+
continue
|
|
166
|
+
lines.append(_sanitize(stripped))
|
|
167
|
+
if "hardcode" in lower or "secret" in lower:
|
|
168
|
+
has_security = True
|
|
169
|
+
lines.append("")
|
|
170
|
+
|
|
171
|
+
# Only add security block if standards didn't already include it
|
|
172
|
+
if not has_security:
|
|
173
|
+
lines += [
|
|
174
|
+
"## Security",
|
|
175
|
+
"- Never hardcode secrets, tokens, or passwords",
|
|
176
|
+
"- Use .env files for environment variables",
|
|
177
|
+
"",
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
# Always include: session-start directive + boundaries
|
|
181
|
+
lines += [
|
|
182
|
+
"## Session Start — READ THESE FILES",
|
|
183
|
+
"At the beginning of every session, read these files for project context:",
|
|
184
|
+
"- `.vibe/state/current.md` — latest progress and sync history",
|
|
185
|
+
"- `.vibe/state/tasks.md` — active task checklist",
|
|
186
|
+
"- `.vibe/VIBE.md` — project constitution and workflow SOP",
|
|
187
|
+
"",
|
|
188
|
+
"## Boundaries",
|
|
189
|
+
"- Do NOT modify `.vibe/config.toml` or `.vibe/state/.lifecycle` directly",
|
|
190
|
+
"- Do NOT run destructive commands without human confirmation",
|
|
191
|
+
"",
|
|
192
|
+
]
|
|
193
|
+
return lines
|
|
194
|
+
|
|
195
|
+
def _warn_validation(self, adapter_name: str) -> None:
|
|
196
|
+
"""Print a validation warning."""
|
|
197
|
+
from rich.console import Console
|
|
198
|
+
|
|
199
|
+
Console().print(
|
|
200
|
+
f"[yellow]Warning:[/] {adapter_name} frontmatter validation failed"
|
|
201
|
+
)
|