gitwise-cli 0.24.2__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.
- gitwise/__init__.py +11 -0
- gitwise/__main__.py +113 -0
- gitwise/_cli_completions.py +88 -0
- gitwise/_cli_dispatch.py +469 -0
- gitwise/_cli_introspection.py +275 -0
- gitwise/_cli_parser.py +345 -0
- gitwise/_cli_setup_agents.py +439 -0
- gitwise/_i18n_data.json +1934 -0
- gitwise/_paths.py +22 -0
- gitwise/_runtime_config.py +246 -0
- gitwise/audit.py +338 -0
- gitwise/branches.py +183 -0
- gitwise/clean.py +197 -0
- gitwise/commit.py +142 -0
- gitwise/conflicts.py +112 -0
- gitwise/context.py +163 -0
- gitwise/design.py +383 -0
- gitwise/diff.py +309 -0
- gitwise/doctor.py +116 -0
- gitwise/git.py +254 -0
- gitwise/health.py +345 -0
- gitwise/i18n.py +99 -0
- gitwise/log.py +329 -0
- gitwise/merge.py +193 -0
- gitwise/optimize.py +212 -0
- gitwise/output.py +652 -0
- gitwise/pick.py +102 -0
- gitwise/pr.py +543 -0
- gitwise/py.typed +0 -0
- gitwise/schema.py +49 -0
- gitwise/setup.py +551 -0
- gitwise/setup_agents/__init__.py +36 -0
- gitwise/setup_agents/adapters/__init__.py +17 -0
- gitwise/setup_agents/adapters/aider.py +5 -0
- gitwise/setup_agents/adapters/base.py +5 -0
- gitwise/setup_agents/adapters/codex.py +5 -0
- gitwise/setup_agents/adapters/continue_adapter.py +5 -0
- gitwise/setup_agents/adapters/cursor.py +5 -0
- gitwise/setup_agents/adapters/opencode.py +5 -0
- gitwise/setup_agents/adapters/pi.py +5 -0
- gitwise/setup_agents/exec.py +449 -0
- gitwise/setup_agents/format.py +164 -0
- gitwise/setup_agents/plan.py +254 -0
- gitwise/setup_agents/plan_gitfiles.py +167 -0
- gitwise/setup_agents/plan_skills.py +256 -0
- gitwise/setup_agents/providers/__init__.py +96 -0
- gitwise/setup_agents/providers/aider.py +11 -0
- gitwise/setup_agents/providers/base.py +79 -0
- gitwise/setup_agents/providers/claude.py +408 -0
- gitwise/setup_agents/providers/codex.py +11 -0
- gitwise/setup_agents/providers/continue_adapter.py +11 -0
- gitwise/setup_agents/providers/cursor.py +11 -0
- gitwise/setup_agents/providers/opencode.py +11 -0
- gitwise/setup_agents/providers/pi.py +11 -0
- gitwise/setup_agents/state.py +141 -0
- gitwise/setup_agents/types.py +48 -0
- gitwise/share/agents/skills/git-audit/SKILL.md +25 -0
- gitwise/share/agents/skills/git-clean/SKILL.md +22 -0
- gitwise/share/agents/skills/git-optimize/SKILL.md +21 -0
- gitwise/share/aider/CONVENTIONS.md.template +8 -0
- gitwise/share/aider/aider.conf.yml.template +4 -0
- gitwise/share/claude/CLAUDE.md.template +9 -0
- gitwise/share/claude/rules/gitwise.md +16 -0
- gitwise/share/claude/settings.json.template +47 -0
- gitwise/share/claude/skills/git-audit/SKILL.md +25 -0
- gitwise/share/claude/skills/git-clean/SKILL.md +22 -0
- gitwise/share/claude/skills/git-optimize/SKILL.md +21 -0
- gitwise/share/codex/agents/gitwise.toml.template +18 -0
- gitwise/share/continue/rules/gitwise.md.template +14 -0
- gitwise/share/cursor/rules/gitwise.mdc.template +16 -0
- gitwise/share/git-config-modern.txt +48 -0
- gitwise/share/hooks/commit-msg +22 -0
- gitwise/share/hooks/pre-commit +19 -0
- gitwise/share/opencode/agents/gitwise.md.template +14 -0
- gitwise/share/pi/skills/gitwise.md.template +14 -0
- gitwise/share/schemas/v1/input/audit.json +40 -0
- gitwise/share/schemas/v1/input/branches.json +51 -0
- gitwise/share/schemas/v1/input/clean.json +52 -0
- gitwise/share/schemas/v1/input/commands.json +36 -0
- gitwise/share/schemas/v1/input/commit.json +63 -0
- gitwise/share/schemas/v1/input/completions.json +51 -0
- gitwise/share/schemas/v1/input/conflicts.json +46 -0
- gitwise/share/schemas/v1/input/context.json +36 -0
- gitwise/share/schemas/v1/input/diff.json +56 -0
- gitwise/share/schemas/v1/input/doctor.json +36 -0
- gitwise/share/schemas/v1/input/health.json +36 -0
- gitwise/share/schemas/v1/input/log.json +71 -0
- gitwise/share/schemas/v1/input/merge.json +63 -0
- gitwise/share/schemas/v1/input/optimize.json +44 -0
- gitwise/share/schemas/v1/input/pick.json +63 -0
- gitwise/share/schemas/v1/input/pr.json +51 -0
- gitwise/share/schemas/v1/input/schema.json +48 -0
- gitwise/share/schemas/v1/input/setup-agents.json +108 -0
- gitwise/share/schemas/v1/input/setup.json +55 -0
- gitwise/share/schemas/v1/input/show.json +46 -0
- gitwise/share/schemas/v1/input/snapshot.json +36 -0
- gitwise/share/schemas/v1/input/stash.json +68 -0
- gitwise/share/schemas/v1/input/status.json +36 -0
- gitwise/share/schemas/v1/input/suggest.json +36 -0
- gitwise/share/schemas/v1/input/summarize.json +44 -0
- gitwise/share/schemas/v1/input/sync.json +55 -0
- gitwise/share/schemas/v1/input/tag.json +73 -0
- gitwise/share/schemas/v1/input/undo.json +60 -0
- gitwise/share/schemas/v1/input/update.json +40 -0
- gitwise/share/schemas/v1/input/worktree.json +50 -0
- gitwise/show.py +118 -0
- gitwise/snapshot.py +110 -0
- gitwise/stash.py +188 -0
- gitwise/status.py +93 -0
- gitwise/suggest.py +148 -0
- gitwise/summarize.py +202 -0
- gitwise/sync.py +257 -0
- gitwise/tag.py +252 -0
- gitwise/undo.py +145 -0
- gitwise/update.py +42 -0
- gitwise/utils/__init__.py +1 -0
- gitwise/utils/git_output.py +51 -0
- gitwise/utils/json_envelope.py +58 -0
- gitwise/utils/parsing.py +34 -0
- gitwise/worktree.py +182 -0
- gitwise_cli-0.24.2.dist-info/METADATA +151 -0
- gitwise_cli-0.24.2.dist-info/RECORD +125 -0
- gitwise_cli-0.24.2.dist-info/WHEEL +4 -0
- gitwise_cli-0.24.2.dist-info/entry_points.txt +2 -0
- gitwise_cli-0.24.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""State detection for setup-agents: path classification, symlink support, GPG readiness."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from gitwise.git import config as git_config
|
|
9
|
+
from gitwise.i18n import t
|
|
10
|
+
from gitwise.setup_agents.types import PathState, StateDict
|
|
11
|
+
|
|
12
|
+
_AGENTS_MD = "AGENTS.md"
|
|
13
|
+
_CLAUDE_MD = "CLAUDE.md"
|
|
14
|
+
_MARKER_RE = re.compile(
|
|
15
|
+
r"^##\s+(Convenciones git para este proyecto|Git conventions for this project)\b",
|
|
16
|
+
re.MULTILINE,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_supports_symlinks_cache: dict[Path, bool] = {}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _gpg_ready(root: Path) -> bool:
|
|
23
|
+
import shutil
|
|
24
|
+
|
|
25
|
+
if not (shutil.which("gpg") or shutil.which("gpg2")):
|
|
26
|
+
return False
|
|
27
|
+
return git_config("commit.gpgsign", cwd=root) == "true" and bool(
|
|
28
|
+
git_config("user.signingkey", cwd=root)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _classify_path(p: Path) -> PathState:
|
|
33
|
+
if p.is_symlink():
|
|
34
|
+
return "symlink_valid" if p.exists() else "symlink_broken"
|
|
35
|
+
if p.exists():
|
|
36
|
+
return "regular"
|
|
37
|
+
return "absent"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _supports_symlinks(root: Path) -> bool:
|
|
41
|
+
if platform.system() == "Windows":
|
|
42
|
+
return False
|
|
43
|
+
if root in _supports_symlinks_cache:
|
|
44
|
+
return _supports_symlinks_cache[root]
|
|
45
|
+
try:
|
|
46
|
+
import tempfile
|
|
47
|
+
|
|
48
|
+
with tempfile.TemporaryDirectory(dir=root) as td:
|
|
49
|
+
link = Path(td) / "_test_link"
|
|
50
|
+
link.symlink_to("_nonexistent")
|
|
51
|
+
link.unlink()
|
|
52
|
+
_supports_symlinks_cache[root] = True
|
|
53
|
+
except (OSError, NotImplementedError):
|
|
54
|
+
_supports_symlinks_cache[root] = False
|
|
55
|
+
return _supports_symlinks_cache[root]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _has_marker(p: Path) -> bool:
|
|
59
|
+
try:
|
|
60
|
+
text = p.read_text(encoding="utf-8")
|
|
61
|
+
return bool(_MARKER_RE.search(text))
|
|
62
|
+
except OSError:
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _files_equal(a: Path, b: Path) -> bool:
|
|
67
|
+
try:
|
|
68
|
+
return a.read_text(encoding="utf-8") == b.read_text(encoding="utf-8")
|
|
69
|
+
except OSError:
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _detect_rules(root: Path) -> list[str]:
|
|
74
|
+
"""Validates .claude/rules/*.md for required globs: frontmatter field."""
|
|
75
|
+
rules_dir = root / ".claude" / "rules"
|
|
76
|
+
warnings: list[str] = []
|
|
77
|
+
if not rules_dir.is_dir():
|
|
78
|
+
return warnings
|
|
79
|
+
root_real = Path(os.path.realpath(str(root)))
|
|
80
|
+
for f in sorted(rules_dir.glob("*.md")):
|
|
81
|
+
f_real = Path(os.path.realpath(str(f)))
|
|
82
|
+
if not f_real.is_relative_to(root_real):
|
|
83
|
+
warnings.append(t("symlink_outside_repo", name=f.name))
|
|
84
|
+
continue
|
|
85
|
+
try:
|
|
86
|
+
if f.stat().st_size > 64_000:
|
|
87
|
+
warnings.append(t("file_too_large", name=f.name))
|
|
88
|
+
continue
|
|
89
|
+
except OSError:
|
|
90
|
+
continue
|
|
91
|
+
try:
|
|
92
|
+
text = f.read_text(encoding="utf-8-sig")
|
|
93
|
+
except OSError:
|
|
94
|
+
continue
|
|
95
|
+
has_frontmatter = text.startswith("---\n")
|
|
96
|
+
fm_end = text.find("\n---\n", 4) if has_frontmatter else -1
|
|
97
|
+
has_globs = "globs:" in text[4:fm_end] if fm_end > 0 else False
|
|
98
|
+
if not (has_frontmatter and has_globs):
|
|
99
|
+
warnings.append(t("missing_globs_frontmatter", name=f.name))
|
|
100
|
+
return warnings
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def reset_caches() -> None:
|
|
104
|
+
_supports_symlinks_cache.clear()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _detect_state(root: Path) -> StateDict:
|
|
108
|
+
agents_md = root / _AGENTS_MD
|
|
109
|
+
claude_md = root / _CLAUDE_MD
|
|
110
|
+
agents_dir = root / ".agents"
|
|
111
|
+
skills_dir = root / ".claude" / "skills"
|
|
112
|
+
|
|
113
|
+
a_state = _classify_path(agents_md)
|
|
114
|
+
c_state = _classify_path(claude_md)
|
|
115
|
+
errors: list[str] = []
|
|
116
|
+
|
|
117
|
+
if a_state == "symlink_broken":
|
|
118
|
+
errors.append(t("symlink_conflict_broken", file=_AGENTS_MD))
|
|
119
|
+
if c_state == "symlink_broken":
|
|
120
|
+
errors.append(t("symlink_conflict_broken", file=_CLAUDE_MD))
|
|
121
|
+
|
|
122
|
+
skills_state = _classify_path(skills_dir)
|
|
123
|
+
skills_target: str | None = None
|
|
124
|
+
if skills_state == "symlink_valid":
|
|
125
|
+
try:
|
|
126
|
+
skills_target = os.readlink(skills_dir)
|
|
127
|
+
except OSError as e:
|
|
128
|
+
errors.append(t("symlink_read_failed", file=".claude/skills", error=str(e)))
|
|
129
|
+
elif skills_state == "symlink_broken":
|
|
130
|
+
errors.append(t("symlink_conflict_broken", file=".claude/skills"))
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
"a_state": a_state,
|
|
134
|
+
"c_state": c_state,
|
|
135
|
+
"agents_dir": agents_dir.is_dir() and not agents_dir.is_symlink(),
|
|
136
|
+
"skills_state": skills_state,
|
|
137
|
+
"skills_target": skills_target,
|
|
138
|
+
"supports_symlinks": _supports_symlinks(root),
|
|
139
|
+
"errors": errors,
|
|
140
|
+
"rules_warnings": _detect_rules(root),
|
|
141
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Typed structures for the setup-agents pipeline (actions, state, plan results)."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Literal, TypedDict
|
|
4
|
+
|
|
5
|
+
ActionDict = dict[str, Any]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
PathState = Literal["absent", "regular", "symlink_valid", "symlink_broken"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StateDict(TypedDict):
|
|
12
|
+
a_state: PathState
|
|
13
|
+
c_state: PathState
|
|
14
|
+
agents_dir: bool
|
|
15
|
+
skills_state: PathState
|
|
16
|
+
skills_target: str | None
|
|
17
|
+
supports_symlinks: bool
|
|
18
|
+
errors: list[str]
|
|
19
|
+
rules_warnings: list[str]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ActionSummary(TypedDict):
|
|
23
|
+
created: int
|
|
24
|
+
appended: int
|
|
25
|
+
symlinked: int
|
|
26
|
+
skipped: int
|
|
27
|
+
errored: int
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_action_summary(actions: list[ActionDict]) -> ActionSummary:
|
|
31
|
+
summary: ActionSummary = {
|
|
32
|
+
"created": 0,
|
|
33
|
+
"appended": 0,
|
|
34
|
+
"symlinked": 0,
|
|
35
|
+
"skipped": 0,
|
|
36
|
+
"errored": 0,
|
|
37
|
+
}
|
|
38
|
+
for a in actions:
|
|
39
|
+
match a.get("action"):
|
|
40
|
+
case "create" | "managed-block-create" | "adapter-create":
|
|
41
|
+
summary["created"] += 1
|
|
42
|
+
case "append" | "merge":
|
|
43
|
+
summary["appended"] += 1
|
|
44
|
+
case "symlink-create":
|
|
45
|
+
summary["symlinked"] += 1
|
|
46
|
+
case "skip" | "symlink-skip" | "managed-block-skip":
|
|
47
|
+
summary["skipped"] += 1
|
|
48
|
+
return summary
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-audit
|
|
3
|
+
description: Diagnostica el repositorio git (ramas stale, commit-graph, fsmonitor, blobs grandes, stashes viejos) y reporta hallazgos priorizados con fixes recomendados. Usa cuando el usuario pida auditar, revisar salud o diagnosticar el repo.
|
|
4
|
+
argument-hint: "[--quick]"
|
|
5
|
+
allowed-tools: Bash(gitwise audit*)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-audit
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Resultado de `gitwise audit --json`:
|
|
14
|
+
|
|
15
|
+
!`gitwise audit --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
Eres un asistente experto en git. Analiza el JSON anterior y produce un reporte breve y accionable:
|
|
20
|
+
|
|
21
|
+
1. **Resumen ejecutivo** (1 línea): estado general del repo.
|
|
22
|
+
2. **Hallazgos priorizados**: lista cada `finding` ordenado por `severity` (critical > high > medium > low > info). Para cada uno indica: `message`, `fix` sugerido, `cost_of_ignore`.
|
|
23
|
+
3. **Acción recomendada**: el comando exacto a ejecutar primero (típicamente el `fix` del finding más severo). NO lo ejecutes — solo recomiéndalo.
|
|
24
|
+
|
|
25
|
+
Si `findings` está vacío, responde "Repo en buen estado" y termina. No inventes hallazgos no presentes en el JSON.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-clean
|
|
3
|
+
description: Lista en dry-run las ramas locales cuyo upstream fue eliminado ([gone]) y reporta cuáles son seguras de borrar. Usa cuando el usuario pida limpiar ramas stale, huérfanas o merged.
|
|
4
|
+
argument-hint: "(sin argumentos)"
|
|
5
|
+
allowed-tools: Bash(gitwise clean --branches --dry-run --json)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-clean
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Resultado de `gitwise clean --branches --dry-run --json`:
|
|
14
|
+
|
|
15
|
+
!`gitwise clean --branches --dry-run --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
1. Reporta el conteo y nombres de ramas en `deletable` y `skipped` (con su `reason`).
|
|
20
|
+
2. Si `deletable` está vacío, responde "No hay ramas stale eliminables" y termina.
|
|
21
|
+
3. Si hay ramas eliminables, sugiere al usuario el comando para borrarlas tras revisión: `gitwise clean --branches --yes`.
|
|
22
|
+
4. NUNCA ejecutes el borrado tú mismo. La versión `--yes` NO está en `allowed-tools` por diseño — requiere confirmación humana explícita.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-optimize
|
|
3
|
+
description: Muestra qué optimizaciones aplicaría gitwise (commit-graph, repack -A -d, prune) en modo dry-run. Usa cuando el usuario pida optimizar git, acelerar log/status, o cuando audit reporte commit-graph ausente.
|
|
4
|
+
argument-hint: "(sin argumentos)"
|
|
5
|
+
allowed-tools: Bash(gitwise optimize --dry-run --json)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-optimize
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Plan de optimización (dry-run):
|
|
14
|
+
|
|
15
|
+
!`gitwise optimize --dry-run --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
1. Lista los `steps` que se ejecutarían (`name`, `desc`).
|
|
20
|
+
2. Estima impacto: commit-graph acelera `git log` 2-10x; repack reduce tamaño y crea bitmap-index; prune libera objetos no referenciados.
|
|
21
|
+
3. Recomienda al usuario ejecutar `gitwise optimize --yes` para aplicarlas. NO ejecutes la versión `--yes` tú mismo: `disable-model-invocation: true` + `allowed-tools` restrictivo lo previenen por diseño.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## Git conventions
|
|
2
|
+
|
|
3
|
+
- Diff: `gitwise diff` (= `git diff --name-status HEAD`). Never raw `git diff`.
|
|
4
|
+
- Log: `git --no-pager log --oneline -n 20`. Never without a limit.
|
|
5
|
+
- Commits: conventional format `feat/fix/refactor/docs/chore: description`.
|
|
6
|
+
- Commits: always GPG-signed. Never `--no-gpg-sign`.
|
|
7
|
+
- Branch switch: `gitwise worktree new <branch>`. Never `git stash + checkout`.
|
|
8
|
+
- Before large commits: `gitwise audit --quick`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Git conventions for this project
|
|
2
|
+
|
|
3
|
+
- Diff: `git diff --stat` or `gitwise summarize`. Never raw `git diff`.
|
|
4
|
+
- Log: `git --no-pager log --oneline -n 20`. Never without a limit.
|
|
5
|
+
- Commits: conventional format `feat/fix/refactor/docs/chore: description`.
|
|
6
|
+
- Commits: always GPG-signed. Never `--no-gpg-sign`.
|
|
7
|
+
- Branch switch: `gitwise worktree new <branch>`. Never `git stash + checkout`.
|
|
8
|
+
- Changed files: `gitwise diff` (= `git diff --name-status HEAD`). Never raw `git diff`.
|
|
9
|
+
- Before large commits: `gitwise audit --quick`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitwise
|
|
3
|
+
description: Use gitwise CLI for git operations — gitwise diff, summarize, worktree
|
|
4
|
+
globs: "**/*"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Use gitwise commands in tool calls
|
|
8
|
+
|
|
9
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
10
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
11
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
12
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
13
|
+
|
|
14
|
+
## Shell note
|
|
15
|
+
|
|
16
|
+
`gw` is a terminal alias only — use `gitwise` or `python -m gitwise` in Bash tool calls.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(gitwise *)",
|
|
5
|
+
"Bash(python -m gitwise *)",
|
|
6
|
+
"Bash(git status*)",
|
|
7
|
+
"Bash(git --no-pager log*)",
|
|
8
|
+
"Bash(git --no-pager diff --stat*)",
|
|
9
|
+
"Bash(git --no-pager diff --name-status*)",
|
|
10
|
+
"Bash(git --no-pager diff --shortstat*)",
|
|
11
|
+
"Bash(git diff --staged*)",
|
|
12
|
+
"Bash(git show*)",
|
|
13
|
+
"Bash(git blame*)",
|
|
14
|
+
"Bash(git for-each-ref*)",
|
|
15
|
+
"Bash(git rev-parse*)",
|
|
16
|
+
"Bash(git ls-files*)",
|
|
17
|
+
"Bash(git branch*)",
|
|
18
|
+
"Bash(git worktree*)",
|
|
19
|
+
"Bash(git add*)",
|
|
20
|
+
"Bash(git commit -S*)",
|
|
21
|
+
"Bash(git commit -m*)"
|
|
22
|
+
],
|
|
23
|
+
"ask": [
|
|
24
|
+
"Bash(git push*)",
|
|
25
|
+
"Bash(git rebase*)",
|
|
26
|
+
"Bash(git reset*)",
|
|
27
|
+
"Bash(git commit --amend*)"
|
|
28
|
+
],
|
|
29
|
+
"deny": [
|
|
30
|
+
"Bash(git push --force*)",
|
|
31
|
+
"Bash(git filter-branch*)",
|
|
32
|
+
"Bash(git clean -fdx*)",
|
|
33
|
+
"Bash(git commit --no-gpg-sign*)",
|
|
34
|
+
"Bash(git commit --no-verify*)",
|
|
35
|
+
"Bash(git commit --allow-empty*)",
|
|
36
|
+
"Bash(git -c commit.gpgsign=false*)",
|
|
37
|
+
"Bash(git -c gpg.format=*)",
|
|
38
|
+
"Bash(git -c core.hooksPath*)",
|
|
39
|
+
"Read(./.env*)",
|
|
40
|
+
"Read(./secrets/**)",
|
|
41
|
+
"Read(**/*.key)",
|
|
42
|
+
"Read(**/*.pem)",
|
|
43
|
+
"Read(**/*.p12)",
|
|
44
|
+
"Read(**/*.pfx)"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-audit
|
|
3
|
+
description: Diagnostica el repositorio git (ramas stale, commit-graph, fsmonitor, blobs grandes, stashes viejos) y reporta hallazgos priorizados con fixes recomendados. Usa cuando el usuario pida auditar, revisar salud o diagnosticar el repo.
|
|
4
|
+
argument-hint: "[--quick]"
|
|
5
|
+
allowed-tools: Bash(gitwise audit*)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-audit
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Resultado de `gitwise audit --json`:
|
|
14
|
+
|
|
15
|
+
!`gitwise audit --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
Eres un asistente experto en git. Analiza el JSON anterior y produce un reporte breve y accionable:
|
|
20
|
+
|
|
21
|
+
1. **Resumen ejecutivo** (1 línea): estado general del repo.
|
|
22
|
+
2. **Hallazgos priorizados**: lista cada `finding` ordenado por `severity` (critical > high > medium > low > info). Para cada uno indica: `message`, `fix` sugerido, `cost_of_ignore`.
|
|
23
|
+
3. **Acción recomendada**: el comando exacto a ejecutar primero (típicamente el `fix` del finding más severo). NO lo ejecutes — solo recomiéndalo.
|
|
24
|
+
|
|
25
|
+
Si `findings` está vacío, responde "Repo en buen estado" y termina. No inventes hallazgos no presentes en el JSON.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-clean
|
|
3
|
+
description: Lista en dry-run las ramas locales cuyo upstream fue eliminado ([gone]) y reporta cuáles son seguras de borrar. Usa cuando el usuario pida limpiar ramas stale, huérfanas o merged.
|
|
4
|
+
argument-hint: "(sin argumentos)"
|
|
5
|
+
allowed-tools: Bash(gitwise clean --branches --dry-run --json)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-clean
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Resultado de `gitwise clean --branches --dry-run --json`:
|
|
14
|
+
|
|
15
|
+
!`gitwise clean --branches --dry-run --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
1. Reporta el conteo y nombres de ramas en `deletable` y `skipped` (con su `reason`).
|
|
20
|
+
2. Si `deletable` está vacío, responde "No hay ramas stale eliminables" y termina.
|
|
21
|
+
3. Si hay ramas eliminables, sugiere al usuario el comando para borrarlas tras revisión: `gitwise clean --branches --yes`.
|
|
22
|
+
4. NUNCA ejecutes el borrado tú mismo. La versión `--yes` NO está en `allowed-tools` por diseño — requiere confirmación humana explícita.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-optimize
|
|
3
|
+
description: Muestra qué optimizaciones aplicaría gitwise (commit-graph, repack -A -d, prune) en modo dry-run. Usa cuando el usuario pida optimizar git, acelerar log/status, o cuando audit reporte commit-graph ausente.
|
|
4
|
+
argument-hint: "(sin argumentos)"
|
|
5
|
+
allowed-tools: Bash(gitwise optimize --dry-run --json)
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# git-optimize
|
|
10
|
+
|
|
11
|
+
## Contexto
|
|
12
|
+
|
|
13
|
+
Plan de optimización (dry-run):
|
|
14
|
+
|
|
15
|
+
!`gitwise optimize --dry-run --json`
|
|
16
|
+
|
|
17
|
+
## Tarea
|
|
18
|
+
|
|
19
|
+
1. Lista los `steps` que se ejecutarían (`name`, `desc`).
|
|
20
|
+
2. Estima impacto: commit-graph acelera `git log` 2-10x; repack reduce tamaño y crea bitmap-index; prune libera objetos no referenciados.
|
|
21
|
+
3. Recomienda al usuario ejecutar `gitwise optimize --yes` para aplicarlas. NO ejecutes la versión `--yes` tú mismo: `disable-model-invocation: true` + `allowed-tools` restrictivo lo previenen por diseño.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name = "gitwise"
|
|
2
|
+
description = "Git workflow conventions — use gitwise CLI for git operations"
|
|
3
|
+
model = "inherit"
|
|
4
|
+
model_reasoning_effort = "inherit"
|
|
5
|
+
sandbox_mode = "inherit"
|
|
6
|
+
|
|
7
|
+
developer_instructions = """
|
|
8
|
+
## Use gitwise commands in tool calls
|
|
9
|
+
|
|
10
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
11
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
12
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
13
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
14
|
+
|
|
15
|
+
## Shell note
|
|
16
|
+
|
|
17
|
+
`gw` is a terminal alias only — use `gitwise` or `python -m gitwise` in Bash tool calls.
|
|
18
|
+
"""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitwise
|
|
3
|
+
description: Use gitwise CLI for git operations — gitwise diff, summarize, worktree
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Use gitwise commands in tool calls
|
|
7
|
+
|
|
8
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
9
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
10
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
11
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
12
|
+
- Audit: `gitwise audit --quick` — before large commits
|
|
13
|
+
- Clean: `gitwise clean --branches` — remove stale branches
|
|
14
|
+
- Optimize: `gitwise optimize` — gc, pack-refs, commit-graph
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use gitwise CLI for git operations — gitwise diff, summarize, worktree
|
|
3
|
+
globs:
|
|
4
|
+
- "**/*"
|
|
5
|
+
alwaysApply: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use gitwise commands in tool calls
|
|
9
|
+
|
|
10
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
11
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
12
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
13
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
14
|
+
- Audit: `gitwise audit --quick` — before large commits
|
|
15
|
+
- Clean: `gitwise clean --branches` — remove stale branches
|
|
16
|
+
- Optimize: `gitwise optimize` — gc, pack-refs, commit-graph
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Subset of GitButler "How Core Git Devs Configure Git" (Chacon, feb 2025)
|
|
2
|
+
# Applied by: gitwise setup
|
|
3
|
+
# Reference: https://blog.gitbutler.com/how-git-core-devs-configure-git/
|
|
4
|
+
|
|
5
|
+
[core]
|
|
6
|
+
# macOS/Windows only — gitwise setup detects platform before applying
|
|
7
|
+
# fsmonitor = true
|
|
8
|
+
untrackedCache = true
|
|
9
|
+
preloadindex = true
|
|
10
|
+
|
|
11
|
+
[fetch]
|
|
12
|
+
prune = true
|
|
13
|
+
prunetags = true
|
|
14
|
+
all = true
|
|
15
|
+
|
|
16
|
+
[merge]
|
|
17
|
+
conflictstyle = zdiff3
|
|
18
|
+
|
|
19
|
+
[diff]
|
|
20
|
+
algorithm = histogram
|
|
21
|
+
colorMoved = default
|
|
22
|
+
|
|
23
|
+
[rerere]
|
|
24
|
+
enabled = true
|
|
25
|
+
autoupdate = true
|
|
26
|
+
|
|
27
|
+
[branch]
|
|
28
|
+
sort = -committerdate
|
|
29
|
+
|
|
30
|
+
[tag]
|
|
31
|
+
sort = -version:refname
|
|
32
|
+
|
|
33
|
+
[push]
|
|
34
|
+
default = current
|
|
35
|
+
autoSetupRemote = true
|
|
36
|
+
|
|
37
|
+
[commit]
|
|
38
|
+
verbose = true
|
|
39
|
+
|
|
40
|
+
[maintenance]
|
|
41
|
+
auto = false
|
|
42
|
+
strategy = incremental
|
|
43
|
+
|
|
44
|
+
# Excluded (matter of taste per GitButler):
|
|
45
|
+
# pull.rebase = true
|
|
46
|
+
|
|
47
|
+
# Gated on git >= 2.40:
|
|
48
|
+
# feature.manyFiles = true
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# gitwise commit-msg hook: verifies conventional commit format
|
|
3
|
+
# Installed by: gitwise setup (legacy core.hooksPath or native Git config hooks)
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Skip format check for git-generated merge/revert/squash/cherry-pick commits
|
|
7
|
+
GIT_DIR="$(git rev-parse --git-dir 2>/dev/null || true)"
|
|
8
|
+
[ -f "${GIT_DIR}/MERGE_HEAD" ] && exit 0
|
|
9
|
+
[ -f "${GIT_DIR}/REBASE_HEAD" ] && exit 0
|
|
10
|
+
[ -f "${GIT_DIR}/CHERRY_PICK_HEAD" ] && exit 0
|
|
11
|
+
[ -f "${GIT_DIR}/SQUASH_MSG" ] && exit 0
|
|
12
|
+
|
|
13
|
+
MSG="$(cat "$1")"
|
|
14
|
+
PATTERN="^(feat|fix|refactor|docs|chore|test|style|perf|ci|build|revert)(\(.+\))?: .{1,72}"
|
|
15
|
+
|
|
16
|
+
if ! printf '%s\n' "$MSG" | grep -qE "$PATTERN"; then
|
|
17
|
+
printf 'gitwise: el mensaje no sigue el formato de conventional commits\n' >&2
|
|
18
|
+
printf ' Esperado: feat: desc | fix(scope): desc | docs: corrección\n' >&2
|
|
19
|
+
printf ' Ejemplos: docs: corrige typo en README | fix: maneja nil en parse\n' >&2
|
|
20
|
+
printf ' Recibido: %s\n' "$MSG" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# gitwise pre-commit hook: verifies GPG signing configuration
|
|
3
|
+
# Installed by: gitwise setup (legacy core.hooksPath or native Git config hooks)
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
gpgsign_val=$(git config --get commit.gpgsign 2>/dev/null || true)
|
|
7
|
+
if [ "$gpgsign_val" = "true" ]; then
|
|
8
|
+
if ! git config --get user.signingkey > /dev/null 2>&1; then
|
|
9
|
+
printf 'gitwise: GPG signing activo pero sin user.signingkey configurado\n' >&2
|
|
10
|
+
printf ' Ejecuta: git config user.signingkey <tu-key-id>\n' >&2
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
signing_key="$(git config user.signingkey)"
|
|
14
|
+
if ! gpg --list-secret-keys "$signing_key" > /dev/null 2>&1; then
|
|
15
|
+
printf 'gitwise: GPG key no encontrada en el keyring: %s\n' "$signing_key" >&2
|
|
16
|
+
printf ' Verifica con: gpg --list-secret-keys\n' >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitwise
|
|
3
|
+
description: Use gitwise CLI for git operations — gitwise diff, summarize, worktree
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Use gitwise commands in tool calls
|
|
7
|
+
|
|
8
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
9
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
10
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
11
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
12
|
+
- Audit: `gitwise audit --quick` — before large commits
|
|
13
|
+
- Clean: `gitwise clean --branches` — remove stale branches
|
|
14
|
+
- Optimize: `gitwise optimize` — gc, pack-refs, commit-graph
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitwise
|
|
3
|
+
description: Use gitwise CLI for git operations — gitwise diff, summarize, worktree
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Use gitwise commands in tool calls
|
|
7
|
+
|
|
8
|
+
- Changed files: `gitwise diff` — never raw `git diff`
|
|
9
|
+
- Status + log: `gitwise summarize` — never raw `git status` or `git log`
|
|
10
|
+
- Branch switch: `gitwise worktree new <branch>` — never `git stash + checkout`
|
|
11
|
+
- Snapshot: `gitwise snapshot` — regenerates `.claude/git-snapshot.md`
|
|
12
|
+
- Audit: `gitwise audit --quick` — before large commits
|
|
13
|
+
- Clean: `gitwise clean --branches` — remove stale branches
|
|
14
|
+
- Optimize: `gitwise optimize` — gc, pack-refs, commit-graph
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://gitwise.dev/schemas/v1/input/audit.json",
|
|
4
|
+
"title": "gitwise audit cli input",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"lang": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"enum": [
|
|
11
|
+
"es",
|
|
12
|
+
"en"
|
|
13
|
+
],
|
|
14
|
+
"description": "output language (default: auto-detect from locale)"
|
|
15
|
+
},
|
|
16
|
+
"theme": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": [
|
|
19
|
+
"dark",
|
|
20
|
+
"light",
|
|
21
|
+
"auto"
|
|
22
|
+
],
|
|
23
|
+
"description": "color theme: dark, light, or auto-detect (default: auto)"
|
|
24
|
+
},
|
|
25
|
+
"json": {
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"description": "output JSON",
|
|
28
|
+
"default": false
|
|
29
|
+
},
|
|
30
|
+
"json_pretty": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "pretty-print JSON output",
|
|
33
|
+
"default": false
|
|
34
|
+
},
|
|
35
|
+
"quick": {
|
|
36
|
+
"type": "boolean",
|
|
37
|
+
"default": false
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|