agex-cli 0.25.0__tar.gz → 0.26.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.
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.github/workflows/publish.yml +5 -4
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.gitignore +1 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/CHANGELOG.md +11 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/CLAUDE.md +21 -20
- {agex_cli-0.25.0 → agex_cli-0.26.0}/PKG-INFO +10 -10
- agex_cli-0.26.0/README.md +29 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/culture.yaml +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/pyproject.toml +6 -6
- {agex_cli-0.25.0 → agex_cli-0.26.0}/sonar-project.properties +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/__init__.py +5 -4
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/__main__.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/acp/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/capabilities/codex.yaml +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/capabilities/copilot.yaml +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/claude_code/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/codex/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/copilot/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/cli.py +65 -32
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/SKILL.md +9 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/references/design.md +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/scripts/doctor.py +34 -35
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/explain/SKILL.md +7 -7
- agex_cli-0.26.0/src/devex/commands/explain/assets/topics/devex.md +39 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/explain/scripts/explain.py +11 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/SKILL.md +7 -7
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/scripts/install.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/SKILL.md +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/scripts/read.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/scripts/write.py +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/cicd/SKILL.md +13 -13
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/gamify/SKILL.md +5 -5
- {agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/levelup → agex_cli-0.26.0/src/devex/commands/learn/assets/topics/gamify}/assets/skill-template/claude-code/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/introspect/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/introspect/assets/skill-template/claude-code/SKILL.md +1 -1
- agex_cli-0.26.0/src/devex/commands/learn/assets/topics/levelup/SKILL.md +31 -0
- {agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/gamify → agex_cli-0.26.0/src/devex/commands/learn/assets/topics/levelup}/assets/skill-template/claude-code/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/visualize/SKILL.md +2 -2
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/topics/visualize/assets/skill-template/claude-code/SKILL.md +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/scripts/learn.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/SKILL.md +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/scripts/overview.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/SKILL.md +45 -17
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/backends/acp.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/backends/claude-code.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/backends/codex.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/backends/copilot.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/rules/lint_rules.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/rules/next_step_rules.py +15 -1
- agex_cli-0.26.0/src/devex/commands/pr/assets/templates/pr_await_detached.md.j2 +29 -0
- agex_cli-0.26.0/src/devex/commands/pr/scripts/_await_worker.py +109 -0
- agex_cli-0.26.0/src/devex/commands/pr/scripts/_detach.py +129 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_footer.py +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_journal.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_qodo.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_readiness.py +4 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_sonar.py +3 -3
- agex_cli-0.26.0/src/devex/commands/pr/scripts/await_.py +395 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/delta.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/lint.py +7 -7
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/open_.py +21 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/read.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/reply.py +9 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/review.py +9 -9
- agex_cli-0.25.0/src/agent_experience/core/hook_io.py → agex_cli-0.26.0/src/devex/core/_jsonl.py +23 -35
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/capabilities.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/config.py +2 -2
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/github.py +2 -2
- agex_cli-0.26.0/src/devex/core/hook_io.py +46 -0
- agex_cli-0.26.0/src/devex/core/journal.py +39 -0
- agex_cli-0.26.0/src/devex/core/paths.py +50 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/prog.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/render.py +1 -1
- agex_cli-0.26.0/tester-agents/claude/.claude/skills +1 -0
- agex_cli-0.26.0/tester-agents/claude/CLAUDE.md +30 -0
- agex_cli-0.26.0/tester-agents/claude/README.md +23 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tester-agents/claude/culture.yaml +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/backends/test_claude_code_probe.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/backends/test_stub_probes.py +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/fixtures/gh/qodo_summary_comment.html +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_await.py +5 -5
- agex_cli-0.26.0/tests/commands/pr/test_await_detach.py +298 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_delta.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_deploy.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_footer.py +9 -7
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_lint.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_lint_rules.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_open.py +71 -12
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_qodo.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_read.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_readiness.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_reply.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/test_review.py +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_doctor.py +28 -28
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_explain.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_gamify.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_hook.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_learn.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_overview.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/test_prog_propagation.py +6 -5
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_backend.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_capabilities.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_config.py +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_github.py +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_hook_io.py +13 -12
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_journal.py +4 -4
- agex_cli-0.26.0/tests/core/test_paths.py +59 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_prog.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_render.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_resolve_backend.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_skill_loader.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/test_version_lookup.py +11 -15
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/test_cli_dispatch.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/test_cli_errors.py +9 -9
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/test_cli_smoke.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/test_skill_md_consistency.py +8 -9
- {agex_cli-0.25.0 → agex_cli-0.26.0}/uv.lock +1 -1
- agex_cli-0.25.0/README.md +0 -29
- agex_cli-0.25.0/src/agent_experience/commands/explain/assets/topics/agex.md +0 -37
- agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/levelup/SKILL.md +0 -31
- agex_cli-0.25.0/src/agent_experience/commands/pr/scripts/await_.py +0 -168
- agex_cli-0.25.0/src/agent_experience/core/journal.py +0 -90
- agex_cli-0.25.0/src/agent_experience/core/paths.py +0 -26
- agex_cli-0.25.0/tester-agents/claude/CLAUDE.md +0 -30
- agex_cli-0.25.0/tester-agents/claude/README.md +0 -23
- agex_cli-0.25.0/tests/core/test_paths.py +0 -31
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/agent-config/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/cicd/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/communicate/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/think/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/think/scripts/think.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.flake8 +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.github/workflows/test.yml +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/.python-version +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/LICENSE +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/skill-sources.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/superpowers/plans/2026-04-18-agex-v0.1.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/superpowers/plans/2026-05-10-agex-pr.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/superpowers/specs/2026-04-18-agex-design.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/superpowers/specs/2026-04-26-agex-doctor.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/docs/superpowers/specs/2026-05-10-agex-pr-design.md +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/acp/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/capabilities/acp.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/capabilities/claude-code.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/claude_code/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/codex/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/copilot/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/assets/report.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/doctor/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/explain/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/explain/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/explain/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/assets/hooks/claude-code.json +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/gamify/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/assets/table.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/hook/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/assets/menu.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/learn/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/assets/backends/acp.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/assets/backends/claude-code.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/assets/backends/codex.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/assets/backends/copilot.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/assets/sections.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/overview/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/backends/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/rules/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/delta.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/footer.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/lint_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/pr_briefing.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/pr_open_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/pr_reply_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/assets/templates/pr_review_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/commands/pr/scripts/_deploy.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/backend.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/core/skill_loader.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tester-agents/claude/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/backends/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/fixtures/gh/.gitkeep +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/fixtures/gh/pr_checks_42.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/fixtures/gh/pr_comments_42.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/commands/pr/fixtures/journals/dogfood_40.jsonl +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/core/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/empty/.gitkeep +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/malformed/.claude/hooks.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/malformed/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/malformed/.claude/skills/bad/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/malformed/.claude/skills/broken-yaml/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/typical/.claude/hooks.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/typical/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/typical/.claude/skills/example/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.0}/tests/fixtures/claude-code/typical/CLAUDE.md +0 -0
|
@@ -73,8 +73,9 @@ jobs:
|
|
|
73
73
|
# because it needs to rewrite the version before building.
|
|
74
74
|
#
|
|
75
75
|
# The matrix exists so we can publish the same code under three PyPI
|
|
76
|
-
# distribution names: `
|
|
77
|
-
# `
|
|
76
|
+
# distribution names: `devex-cli` (canonical) plus the `agent-devex` and
|
|
77
|
+
# `agex-cli` aliases (`agex-cli` is the legacy canonical name, still
|
|
78
|
+
# published for back-compat). Each leg rewrites `[project].name` in pyproject.toml
|
|
78
79
|
# before building so each wheel is uploaded under its own Trusted Publishing
|
|
79
80
|
# project.
|
|
80
81
|
# --------------------------------------------------------------------------
|
|
@@ -97,9 +98,9 @@ jobs:
|
|
|
97
98
|
- run: uv venv
|
|
98
99
|
- run: uv pip install build
|
|
99
100
|
|
|
100
|
-
# Rewrite `[project].name` to the matrix dist name. For `
|
|
101
|
+
# Rewrite `[project].name` to the matrix dist name. For `devex-cli`
|
|
101
102
|
# (the canonical dist) the regex still has to match so we re-emit
|
|
102
|
-
# the line; for `agent-devex` / `
|
|
103
|
+
# the line; for `agent-devex` / `agex-cli` it produces an alias dist
|
|
103
104
|
# with identical contents. The post-rewrite re-parse is a fail-closed
|
|
104
105
|
# check: if a future formatting change breaks the regex match (or
|
|
105
106
|
# `[project].name` ends up wrong for any reason), the job aborts
|
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.26.0] - 2026-05-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`devex pr await <PR> --detach` / `--check`** — non-blocking await (#64). `--detach` forks a detached background poller that runs the same readiness → CI → Sonar-gate → thread-tally logic, writes the verdict to a marker (`.devex/data/pr/<PR>/await.json`, atomic `os.replace`), and returns immediately — taking the in-session `time.sleep` (and the prompt-cache re-read tax past the ~5-min TTL) out of the agent's context. `--check` reads that marker back without sleeping or re-polling: the stored briefing + the same non-zero-on-blocked exit code when done, a "still polling (started Ns ago)" notice while running, and a clear notice (never a crash or false "clean") when no run exists or the marker schema is incompatible. The detached worker always leaves a marker — even on `gh` failure, and even if the spawn itself fails — so `--check` is never left hanging. The two flags are mutually exclusive. New per-backend footer keys (`await_detached`, `await_check_pending`, `await_check_missing`, `await_check_incompatible`) ship for all four backends.
|
|
15
|
+
- **`devex pr open --detached-await`** — auto-wait at open time: after creating the PR (and posting the Qodo trigger), fork the detached `pr await` poller and return immediately, so "open → walk away → `pr await <PR> --check`" is one command. The non-blocking counterpart to `--delayed-read` (the two are mutually exclusive).
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **Renamed the tool from `agex` to `devex` end to end** — `devex` is now the canonical command, `devex-cli` the canonical PyPI distribution, and the Python module is `devex` (was `agent_experience`). The on-disk state directory is `.devex/` (was `.agex/`), with a transparent read-fallback to a pre-existing `.agex/` and a one-time migration on first write. **`agex` stays a fully working, non-breaking alias**: the `agex` console script and `agex-cli` distribution are still published, `agex` is still recognized as an invoked name, and `devex explain agex` resolves to the overview page. Kept stable for back-compat: the `agex_version` config-file key, the `agex:` gamify hook-fragment IDs, and the `agex hook write` command in the shipped hook asset.
|
|
20
|
+
|
|
10
21
|
## [0.25.0] - 2026-05-29
|
|
11
22
|
|
|
12
23
|
### Added
|
|
@@ -4,24 +4,24 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Project
|
|
6
6
|
|
|
7
|
-
`
|
|
7
|
+
`devex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. Published on PyPI under three distribution names: `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — the same wheel each time. CLI entry points: `devex` (canonical) and `agex` (legacy alias) — both invoke the same tool; emitted output reflects whichever name was typed. GitHub repo: `agentculture/devex`. Python module: `devex` (renamed from `agent_experience`).
|
|
8
8
|
|
|
9
9
|
**Source-of-truth documents:**
|
|
10
10
|
|
|
11
11
|
- Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`
|
|
12
12
|
- Implementation plan: `docs/superpowers/plans/2026-04-18-agex-v0.1.md` — 33 tasks across 12 phases.
|
|
13
|
-
- Status: PR #1 merged Phases 1–3 (scaffolding, core, `
|
|
13
|
+
- Status: PR #1 merged Phases 1–3 (scaffolding, core, `devex explain`). Phases 4–12 (`overview`, `learn`, `gamify`, `hook`, backends, docs site, tester) remain.
|
|
14
14
|
|
|
15
15
|
Read the spec before any non-trivial change — the design invariants below are derived from it.
|
|
16
16
|
|
|
17
17
|
## Design invariants (non-negotiable)
|
|
18
18
|
|
|
19
|
-
1. **Zero LLM calls inside
|
|
19
|
+
1. **Zero LLM calls inside devex.** All output is deterministic markdown from Jinja templates + Python.
|
|
20
20
|
2. **Markdown is the only output format.** No `--json` flag.
|
|
21
21
|
3. **`--agent <backend>` is required** on backend-sensitive commands. The CLI never auto-detects.
|
|
22
|
-
4. **Side effects only in** `gamify`, `gamify --uninstall`, `hook write`, `pr open`, `pr reply`, `pr review`, `pr read` (journal writes), and first-run `.
|
|
22
|
+
4. **Side effects only in** `gamify`, `gamify --uninstall`, `hook write`, `pr open`, `pr reply`, `pr review`, `pr read` (journal writes), `pr await` (journal + `--detach` marker writes under `.devex/data/pr/<pr>/` and the detached poller subprocess), and first-run `.devex/` init. Everything else is read-only. The `devex pr` namespace allows scoped network I/O (via `gh`), bounded `--wait` sleep, and — for `pr await --detach` — a detached background process that pays that sleep outside the agent session; a deliberate carve-out from the no-network/no-sleep invariants.
|
|
23
23
|
5. **"Unsupported" is success** — exit 0 with a markdown notice that links to the issue tracker, not a non-zero exit.
|
|
24
|
-
6. **Skills are authored by the agent, not shipped by
|
|
24
|
+
6. **Skills are authored by the agent, not shipped by devex.** `devex learn <topic>` teaches; `devex explain <topic>` describes; devex never writes a user skill file on the agent's behalf in v0.1.
|
|
25
25
|
|
|
26
26
|
## Architecture (3-stage pipeline)
|
|
27
27
|
|
|
@@ -36,17 +36,18 @@ cli.py ──► commands/<name>/scripts/<name>.py ──► core/render.py
|
|
|
36
36
|
(supported / unsupported)
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
- `cli.py` (Typer) routes `
|
|
40
|
-
- Each `commands/<name>/` is a **skill-folder**: `SKILL.md` + `scripts/` + `assets/` + `references/`. The `SKILL.md` doubles as the content emitted by `
|
|
41
|
-
- `core/` is shared plumbing — backend enum, `.
|
|
39
|
+
- `cli.py` (Typer) routes `devex <command> [args] --agent X`. No business logic.
|
|
40
|
+
- Each `commands/<name>/` is a **skill-folder**: `SKILL.md` + `scripts/` + `assets/` + `references/`. The `SKILL.md` doubles as the content emitted by `devex explain <command>`.
|
|
41
|
+
- `core/` is shared plumbing — backend enum, `.devex/` paths, Jinja renderer (`StrictUndefined`), TOML config, SKILL.md frontmatter parser, capability matrix loader, hook JSON I/O. Command- and content-agnostic.
|
|
42
42
|
- A backend lives in three places: `core/backend.Backend` (enum entry), `backends/<name>/probe.py` (optional Python probe), and one YAML per relevant command under `commands/*/assets/backends/<name>.yaml`. Adding a backend touches only those locations.
|
|
43
43
|
|
|
44
|
-
## `
|
|
44
|
+
## `devex pr` namespace (v0.17.0+)
|
|
45
45
|
|
|
46
|
-
`lint`, `open`, `read`, `reply`, `review`, `await`, `delta`. Each command ends with a deterministic "Next step:" footer. The `pr` namespace allows scoped network I/O (via `gh`) and bounded `--wait` sleep — a deliberate carve-out from the no-network/no-sleep invariants. `pr open` (non-draft, new PR) and `pr review` post the Qodo `/agentic_review` trigger comment; the legacy `/improve` is deprecated and never emitted. The trigger string lives in one place: `commands/pr/scripts/review.QODO_REVIEW_TRIGGER`. Key modules:
|
|
46
|
+
`lint`, `open`, `read`, `reply`, `review`, `await`, `delta`. Each command ends with a deterministic "Next step:" footer. The `pr` namespace allows scoped network I/O (via `gh`) and bounded `--wait` sleep — a deliberate carve-out from the no-network/no-sleep invariants. `pr open` (non-draft, new PR) and `pr review` post the Qodo `/agentic_review` trigger comment; the legacy `/improve` is deprecated and never emitted. The trigger string lives in one place: `commands/pr/scripts/review.QODO_REVIEW_TRIGGER`. `pr await --detach` / `--check` (issue #64) move the bounded poll out of the agent session: `--detach` forks a detached worker (`commands/pr/scripts/_await_worker.py`) that writes the verdict to a marker (`commands/pr/scripts/_detach.py`, atomic `os.replace`), and `--check` reads it back without sleeping. Key modules:
|
|
47
47
|
|
|
48
48
|
- `core/github.py` — thin `gh` shellout wrapper; future zero-trust httpx swap touches only this file.
|
|
49
|
-
- `
|
|
49
|
+
- `commands/pr/scripts/_detach.py` — await-marker read/write (atomic) + the detached-subprocess spawn helper.
|
|
50
|
+
- `core/journal.py` — nested-stream JSONL append/load for `.devex/data/<dir>/<stream>.jsonl`.
|
|
50
51
|
- `core/backend.resolve_backend()` — `--agent` resolution with `culture.yaml` fallback.
|
|
51
52
|
- `commands/pr/assets/rules/next_step_rules.py` — "Next step:" footer decision logic, per-backend phrasing under `commands/pr/assets/backends/<backend>.yaml`.
|
|
52
53
|
|
|
@@ -57,8 +58,8 @@ Spec: `docs/superpowers/specs/2026-05-10-agex-pr-design.md`. Plan: `docs/superpo
|
|
|
57
58
|
- **Resource loading: use `importlib.resources.files(...)` and treat the result as a `Traversable`.** Call `.joinpath()` / `.is_file()` / `.read_text(encoding="utf-8")` directly. Wrap with `importlib.resources.as_file()` only when a third-party API needs a real `pathlib.Path`. Do NOT do `Path(str(files(...)))` — it's not zipapp/PEX safe.
|
|
58
59
|
- **File locking: use `portalocker.lock` / `portalocker.unlock`.** Reaching for `fcntl.flock` / `msvcrt.locking` directly is a known foot-gun on Windows (see commit `923f639`).
|
|
59
60
|
- **Always pass `encoding="utf-8"` to `read_text` / `write_text`.** Default locale on Windows corrupts non-ASCII output.
|
|
60
|
-
- **Validate user-controlled CLI args before joining into paths.** `
|
|
61
|
-
- **Single source of truth for the version:** `pyproject.toml`. `
|
|
61
|
+
- **Validate user-controlled CLI args before joining into paths.** `devex explain <topic>` rejects anything that doesn't match `^[a-z][a-z0-9-]*$` to block path traversal (commit `5ac796e`, test `test_explain_rejects_path_traversal`).
|
|
62
|
+
- **Single source of truth for the version:** `pyproject.toml`. `devex.__version__` derives from installed distribution metadata via `importlib.metadata.version("devex-cli")` (falling back to the `agent-devex` / `agex-cli` alias dists, then pyproject), and `Config.agex_version` derives from `__version__` via `field(default_factory=...)`. (The `agex_version` config-file key name is kept for back-compat with existing `.devex/config.toml` / `.agex/config.toml` files.) Bumping the version means editing `pyproject.toml` only — no `__init__.py` edit needed.
|
|
62
63
|
|
|
63
64
|
## Common commands
|
|
64
65
|
|
|
@@ -73,12 +74,12 @@ uv run pytest
|
|
|
73
74
|
uv run pytest tests/core/test_paths.py::test_ensure_init_creates_dir_and_gitignore -v
|
|
74
75
|
|
|
75
76
|
# Run the CLI
|
|
76
|
-
uv run
|
|
77
|
-
uv run
|
|
78
|
-
uv run
|
|
77
|
+
uv run devex --version
|
|
78
|
+
uv run devex explain devex
|
|
79
|
+
uv run devex explain explain
|
|
79
80
|
|
|
80
81
|
# Coverage (matches what build.yml runs; SonarCloud reads this file)
|
|
81
|
-
uv run pytest --cov=src/
|
|
82
|
+
uv run pytest --cov=src/devex --cov-report=xml --cov-report=term
|
|
82
83
|
```
|
|
83
84
|
|
|
84
85
|
## CI surface
|
|
@@ -90,7 +91,7 @@ uv run pytest --cov=src/agent_experience --cov-report=xml --cov-report=term
|
|
|
90
91
|
|
|
91
92
|
## SonarCloud notes
|
|
92
93
|
|
|
93
|
-
- `python:S5496` is **narrowly suppressed** for `src/
|
|
94
|
+
- `python:S5496` is **narrowly suppressed** for `src/devex/core/render.py` only via `sonar.issue.ignore.multicriteria` in `sonar-project.properties`. Reason: `render_string()` renders Jinja templates that are always package-shipped; output is markdown, never HTML in a browser. See the comment in `render.py` above `render_string` for the rationale. Do not widen the suppression to other files.
|
|
94
95
|
- The `render.py` autoescape decision is explicit (`autoescape=select_autoescape([])`). Don't change it.
|
|
95
96
|
|
|
96
97
|
## Git workflow
|
|
@@ -100,6 +101,6 @@ uv run pytest --cov=src/agent_experience --cov-report=xml --cov-report=term
|
|
|
100
101
|
- Push, open a PR, let CI + SonarCloud + Qodo + Copilot run. Address inline comments + resolve threads before merge.
|
|
101
102
|
- Merging to `main` publishes to PyPI automatically (via `autotag` → `publish-pypi` → `github-release` in `publish.yml`). No manual tagging.
|
|
102
103
|
- When posting on GitHub on the user's behalf (PR descriptions, issue replies, review-thread replies), sign so it's clear the message came from an AI. Three conventions, in priority order:
|
|
103
|
-
- **`
|
|
104
|
+
- **`devex pr open` / `devex pr reply`** — auto-append `- devex-cli (Claude)` (the nick is resolved from `culture.yaml` via `core.github.resolve_nick`, falling back to the repo basename). Don't sign manually.
|
|
104
105
|
- **Inside `communicate` workflow scripts** (`post-issue.sh`, `post-comment.sh`) — `agtag` resolves the same nick from `culture.yaml`. Don't sign manually.
|
|
105
|
-
- **Manual posts the scripts didn't author** (a hand-typed `gh pr create --body …`, a one-off review reply) — sign explicitly as `-
|
|
106
|
+
- **Manual posts the scripts didn't author** (a hand-typed `gh pr create --body …`, a one-off review reply) — sign explicitly as `- devex-cli (Claude)`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agex-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.26.0
|
|
4
4
|
Summary: Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents.
|
|
5
|
-
Project-URL: Homepage, https://culture.dev/
|
|
5
|
+
Project-URL: Homepage, https://culture.dev/devex/
|
|
6
6
|
Project-URL: Repository, https://github.com/agentculture/devex
|
|
7
7
|
Project-URL: Issues, https://github.com/agentculture/devex/issues
|
|
8
8
|
Author: Ori Nachum
|
|
@@ -24,29 +24,29 @@ Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
|
24
24
|
Requires-Dist: syrupy>=4.6; extra == 'dev'
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# devex
|
|
28
28
|
|
|
29
|
-
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `
|
|
29
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — and installs two equivalent commands, `devex` (canonical) and `agex` (legacy alias) (emitted output reflects whichever name you invoke).
|
|
30
30
|
|
|
31
31
|
## Install
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
uv tool install
|
|
34
|
+
uv tool install devex-cli # or: agex-cli
|
|
35
35
|
# or
|
|
36
|
-
pipx install
|
|
36
|
+
pipx install devex-cli # or: pipx install agex-cli
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Quick start
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
devex explain devex
|
|
43
|
+
devex overview --agent claude-code
|
|
44
|
+
devex learn --agent claude-code
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## Docs
|
|
48
48
|
|
|
49
|
-
[culture.dev/
|
|
49
|
+
[culture.dev/devex](https://culture.dev/devex/).
|
|
50
50
|
|
|
51
51
|
Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`.
|
|
52
52
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# devex
|
|
2
|
+
|
|
3
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — and installs two equivalent commands, `devex` (canonical) and `agex` (legacy alias) (emitted output reflects whichever name you invoke).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv tool install devex-cli # or: agex-cli
|
|
9
|
+
# or
|
|
10
|
+
pipx install devex-cli # or: pipx install agex-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
devex explain devex
|
|
17
|
+
devex overview --agent claude-code
|
|
18
|
+
devex learn --agent claude-code
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Docs
|
|
22
|
+
|
|
23
|
+
[culture.dev/devex](https://culture.dev/devex/).
|
|
24
|
+
|
|
25
|
+
Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`.
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agex-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.26.0"
|
|
4
4
|
description = "Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents."
|
|
5
5
|
authors = [{name = "Ori Nachum"}]
|
|
6
6
|
license = {text = "MIT"}
|
|
@@ -26,11 +26,11 @@ dev = [
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
[project.scripts]
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
devex = "devex.cli:_main_entrypoint"
|
|
30
|
+
agex = "devex.cli:_main_entrypoint"
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
|
-
Homepage = "https://culture.dev/
|
|
33
|
+
Homepage = "https://culture.dev/devex/"
|
|
34
34
|
Repository = "https://github.com/agentculture/devex"
|
|
35
35
|
Issues = "https://github.com/agentculture/devex/issues"
|
|
36
36
|
|
|
@@ -39,7 +39,7 @@ requires = ["hatchling"]
|
|
|
39
39
|
build-backend = "hatchling.build"
|
|
40
40
|
|
|
41
41
|
[tool.hatch.build.targets.wheel]
|
|
42
|
-
packages = ["src/
|
|
42
|
+
packages = ["src/devex"]
|
|
43
43
|
|
|
44
44
|
[tool.pytest.ini_options]
|
|
45
45
|
testpaths = ["tests"]
|
|
@@ -54,7 +54,7 @@ line_length = 100
|
|
|
54
54
|
|
|
55
55
|
[tool.bandit]
|
|
56
56
|
# B311 flags any `random.*` usage as potentially unsafe for crypto purposes.
|
|
57
|
-
# `core/
|
|
57
|
+
# `core/_jsonl.acquire_lock_with_retry` uses `random.uniform` purely for
|
|
58
58
|
# backoff jitter between bounded retries -- not a security context, so the
|
|
59
59
|
# standard `random` module is the right choice (secrets would be misuse).
|
|
60
60
|
skips = ["B311"]
|
|
@@ -30,17 +30,17 @@ sonar.python.coverage.reportPaths=coverage.xml
|
|
|
30
30
|
# S2083 (path injection) fires in commands/gamify/scripts/install.py because
|
|
31
31
|
# the hooks file path is `Path.cwd() / ".claude" / "hooks.json"`. `Path.cwd()`
|
|
32
32
|
# is the process's working directory (set by the user's shell before invoking
|
|
33
|
-
#
|
|
33
|
+
# devex); `.claude` and `hooks.json` are hardcoded literals. No HTTP body, CLI
|
|
34
34
|
# string argument, or other network/request input is ever joined into this
|
|
35
35
|
# path — the backend name is enum-validated by `parse_backend()` before reaching
|
|
36
36
|
# install.py and does not itself flow into the path. S2083 is designed for
|
|
37
37
|
# web contexts where a request-body filename taints a filesystem call; that
|
|
38
38
|
# threat model does not apply here. Writing `.claude/hooks.json` is the
|
|
39
|
-
# documented contract of `
|
|
39
|
+
# documented contract of `devex gamify` (design spec invariant #4: "Side
|
|
40
40
|
# effects only in gamify, gamify --uninstall, hook write, and first-run
|
|
41
|
-
# `.
|
|
41
|
+
# `.devex/` init"). Rule is disabled only for this one file.
|
|
42
42
|
sonar.issue.ignore.multicriteria=e1,e2
|
|
43
43
|
sonar.issue.ignore.multicriteria.e1.ruleKey=pythonsecurity:S5496
|
|
44
|
-
sonar.issue.ignore.multicriteria.e1.resourceKey=src/
|
|
44
|
+
sonar.issue.ignore.multicriteria.e1.resourceKey=src/devex/core/render.py
|
|
45
45
|
sonar.issue.ignore.multicriteria.e2.ruleKey=pythonsecurity:S2083
|
|
46
|
-
sonar.issue.ignore.multicriteria.e2.resourceKey=src/
|
|
46
|
+
sonar.issue.ignore.multicriteria.e2.resourceKey=src/devex/commands/gamify/scripts/install.py
|
|
@@ -2,14 +2,15 @@ from importlib.metadata import PackageNotFoundError, version
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def _resolve_version() -> str:
|
|
5
|
-
# `
|
|
6
|
-
# `
|
|
7
|
-
# different names
|
|
5
|
+
# `devex-cli` is the canonical PyPI distribution name; `agent-devex` and
|
|
6
|
+
# `agex-cli` are alias distributions that ship the identical wheel under
|
|
7
|
+
# different names (`agex-cli` is the legacy canonical name, kept published
|
|
8
|
+
# for back-compat). Whichever one is installed, surface its metadata
|
|
8
9
|
# version. As a final fallback for unbuilt source checkouts (no installed
|
|
9
10
|
# dist metadata), read the version directly from the repo's pyproject.toml
|
|
10
11
|
# so the version stays single-sourced from pyproject.toml in every
|
|
11
12
|
# reachable code path.
|
|
12
|
-
for dist in ("
|
|
13
|
+
for dist in ("devex-cli", "agent-devex", "agex-cli"):
|
|
13
14
|
try:
|
|
14
15
|
return version(dist)
|
|
15
16
|
except PackageNotFoundError:
|
{agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.0/src/devex}/backends/capabilities/codex.yaml
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
hooks: false
|
|
2
2
|
hooks_alternative: |
|
|
3
3
|
Codex does not expose a hook interface. Wrap your Codex invocation in a shell
|
|
4
|
-
script that calls `
|
|
4
|
+
script that calls `devex hook write` before/after each turn as a workaround.
|
|
5
5
|
mcp: true
|
|
6
6
|
skills: false
|
|
7
7
|
agents: false
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
hooks: false
|
|
2
2
|
hooks_alternative: |
|
|
3
3
|
GitHub Copilot CLI does not expose a hook interface in v0.1-era versions.
|
|
4
|
-
Track usage via a shell wrapper that calls `
|
|
4
|
+
Track usage via a shell wrapper that calls `devex hook write`.
|
|
5
5
|
mcp: false
|
|
6
6
|
skills: false
|
|
7
7
|
agents: false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""devex CLI — stdlib argparse front end.
|
|
2
2
|
|
|
3
|
-
No third-party CLI framework: this module routes `
|
|
3
|
+
No third-party CLI framework: this module routes `devex <command> [args]`
|
|
4
4
|
through `argparse` only, mirroring the skeleton used by the sibling Culture
|
|
5
5
|
repos (steward, devague). Business logic stays in `commands/<name>/scripts/`,
|
|
6
6
|
which return ``(stdout, exit_code, stderr)`` tuples; this module just parses
|
|
@@ -13,23 +13,23 @@ import sys
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import Optional
|
|
15
15
|
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
30
|
-
from
|
|
31
|
-
from
|
|
32
|
-
from
|
|
16
|
+
from devex import __version__
|
|
17
|
+
from devex.commands.doctor.scripts import doctor as doctor_script
|
|
18
|
+
from devex.commands.explain.scripts import explain as explain_script
|
|
19
|
+
from devex.commands.gamify.scripts import install as gamify_script
|
|
20
|
+
from devex.commands.hook.scripts import read as hook_read_script
|
|
21
|
+
from devex.commands.hook.scripts import write as hook_write_script
|
|
22
|
+
from devex.commands.learn.scripts import learn as learn_script
|
|
23
|
+
from devex.commands.overview.scripts import overview as overview_script
|
|
24
|
+
from devex.commands.pr.scripts import await_ as pr_await_script
|
|
25
|
+
from devex.commands.pr.scripts import delta as pr_delta_script
|
|
26
|
+
from devex.commands.pr.scripts import lint as pr_lint_script
|
|
27
|
+
from devex.commands.pr.scripts import open_ as pr_open_script
|
|
28
|
+
from devex.commands.pr.scripts import read as pr_read_script
|
|
29
|
+
from devex.commands.pr.scripts import reply as pr_reply_script
|
|
30
|
+
from devex.commands.pr.scripts import review as pr_review_script
|
|
31
|
+
from devex.core.backend import parse_backend
|
|
32
|
+
from devex.core.prog import prog_name
|
|
33
33
|
|
|
34
34
|
_AGENT_HELP = "Backend: claude-code, codex, copilot, or acp."
|
|
35
35
|
|
|
@@ -43,7 +43,7 @@ class _AgexArgumentParser(argparse.ArgumentParser):
|
|
|
43
43
|
"""ArgumentParser used everywhere via ``parser_class=``.
|
|
44
44
|
|
|
45
45
|
argparse's native ``error()`` already prints usage to stderr and exits
|
|
46
|
-
with code 2 — which matches
|
|
46
|
+
with code 2 — which matches devex's existing bad-argument behavior — so no
|
|
47
47
|
override is required. The subclass exists only so nested subparsers inherit
|
|
48
48
|
it and to give a single place for any future tweak.
|
|
49
49
|
"""
|
|
@@ -177,6 +177,7 @@ def _cmd_pr_open(args: argparse.Namespace) -> int:
|
|
|
177
177
|
body_file=args.body_file,
|
|
178
178
|
draft=args.draft,
|
|
179
179
|
delayed_read=args.delayed_read,
|
|
180
|
+
detached_await=args.detached_await,
|
|
180
181
|
)
|
|
181
182
|
except ValueError as exc:
|
|
182
183
|
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
@@ -224,9 +225,18 @@ def _cmd_pr_read(args: argparse.Namespace) -> int:
|
|
|
224
225
|
|
|
225
226
|
def _cmd_pr_await(args: argparse.Namespace) -> int:
|
|
226
227
|
try:
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
if args.check:
|
|
229
|
+
stdout, exit_code, stderr = pr_await_script.check(
|
|
230
|
+
agent=args.agent, project_dir=Path.cwd(), pr=args.pr
|
|
231
|
+
)
|
|
232
|
+
elif args.detach:
|
|
233
|
+
stdout, exit_code, stderr = pr_await_script.detach(
|
|
234
|
+
agent=args.agent, project_dir=Path.cwd(), pr=args.pr, max_wait=args.max_wait
|
|
235
|
+
)
|
|
236
|
+
else:
|
|
237
|
+
stdout, exit_code, stderr = pr_await_script.run(
|
|
238
|
+
agent=args.agent, project_dir=Path.cwd(), pr=args.pr, max_wait=args.max_wait
|
|
239
|
+
)
|
|
230
240
|
except ValueError as exc:
|
|
231
241
|
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
232
242
|
return 2
|
|
@@ -280,7 +290,7 @@ def _add_agent_option(parser: argparse.ArgumentParser, *, required: bool, help_t
|
|
|
280
290
|
def _group_help(parser: argparse.ArgumentParser):
|
|
281
291
|
"""Return a handler that prints a group's help to stderr and exits 2.
|
|
282
292
|
|
|
283
|
-
Mirrors Typer's ``no_args_is_help`` for ``
|
|
293
|
+
Mirrors Typer's ``no_args_is_help`` for ``devex hook`` / ``devex pr`` invoked
|
|
284
294
|
with no subcommand.
|
|
285
295
|
"""
|
|
286
296
|
|
|
@@ -305,7 +315,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
305
315
|
p_explain.set_defaults(func=_cmd_explain)
|
|
306
316
|
|
|
307
317
|
# doctor
|
|
308
|
-
p_doctor = sub.add_parser("doctor", help="Diagnose the project's
|
|
318
|
+
p_doctor = sub.add_parser("doctor", help="Diagnose the project's devex setup.")
|
|
309
319
|
p_doctor.add_argument(
|
|
310
320
|
"--role", default=None, help="Render a role-specific check section (e.g., pr-review)."
|
|
311
321
|
)
|
|
@@ -335,7 +345,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
335
345
|
|
|
336
346
|
|
|
337
347
|
def _register_hook(sub: argparse._SubParsersAction) -> None:
|
|
338
|
-
hook_p = sub.add_parser("hook", help="Write and read
|
|
348
|
+
hook_p = sub.add_parser("hook", help="Write and read devex tracking events.")
|
|
339
349
|
hook_sub = hook_p.add_subparsers(dest="hook_command", parser_class=_AgexArgumentParser)
|
|
340
350
|
|
|
341
351
|
p_write = hook_sub.add_parser("write", help="Append a tracking event.")
|
|
@@ -372,11 +382,18 @@ def _register_pr(sub: argparse._SubParsersAction) -> None:
|
|
|
372
382
|
p_open.add_argument("--body-file", type=Path, default=None)
|
|
373
383
|
p_open.add_argument("--draft", action="store_true", default=False)
|
|
374
384
|
_add_agent_option(p_open, required=False, help_text=_AGENT_HELP)
|
|
375
|
-
p_open.
|
|
385
|
+
open_wait_group = p_open.add_mutually_exclusive_group()
|
|
386
|
+
open_wait_group.add_argument(
|
|
376
387
|
"--delayed-read",
|
|
377
388
|
action="store_true",
|
|
378
389
|
default=False,
|
|
379
|
-
help="After create, immediately run `pr read --wait 180
|
|
390
|
+
help="After create, immediately run `pr read --wait 180` (blocks this session).",
|
|
391
|
+
)
|
|
392
|
+
open_wait_group.add_argument(
|
|
393
|
+
"--detached-await",
|
|
394
|
+
action="store_true",
|
|
395
|
+
default=False,
|
|
396
|
+
help="After create, fork a detached `pr await` poller; return now (read with --check).",
|
|
380
397
|
)
|
|
381
398
|
p_open.set_defaults(func=_cmd_pr_open)
|
|
382
399
|
|
|
@@ -417,6 +434,22 @@ def _register_pr(sub: argparse._SubParsersAction) -> None:
|
|
|
417
434
|
"returns early (down to waited=0s) once satisfied (default 1800)."
|
|
418
435
|
),
|
|
419
436
|
)
|
|
437
|
+
detach_group = p_await.add_mutually_exclusive_group()
|
|
438
|
+
detach_group.add_argument(
|
|
439
|
+
"--detach",
|
|
440
|
+
action="store_true",
|
|
441
|
+
default=False,
|
|
442
|
+
help=(
|
|
443
|
+
"Fork a background poller that writes the verdict to a marker and "
|
|
444
|
+
"return immediately (no in-session sleep). Read it later with --check."
|
|
445
|
+
),
|
|
446
|
+
)
|
|
447
|
+
detach_group.add_argument(
|
|
448
|
+
"--check",
|
|
449
|
+
action="store_true",
|
|
450
|
+
default=False,
|
|
451
|
+
help="Read a --detach run's marker without sleeping; print the verdict (or still-polling).",
|
|
452
|
+
)
|
|
420
453
|
_add_agent_option(p_await, required=False, help_text=_AGENT_HELP)
|
|
421
454
|
p_await.set_defaults(func=_cmd_pr_await)
|
|
422
455
|
|
|
@@ -462,10 +495,10 @@ _KNOWN_COMMANDS = {"explain", "overview", "learn", "gamify", "hook", "doctor", "
|
|
|
462
495
|
|
|
463
496
|
|
|
464
497
|
def _main_entrypoint() -> None:
|
|
465
|
-
"""CLI entry point that routes unknown subcommands to ``
|
|
498
|
+
"""CLI entry point that routes unknown subcommands to ``devex explain devex``.
|
|
466
499
|
|
|
467
500
|
When the first positional argument is not a known command (and is not a
|
|
468
|
-
flag), print the ``
|
|
501
|
+
flag), print the ``devex explain devex`` page to stdout and the canonical
|
|
469
502
|
error message to stderr, then exit with code 2. All other invocations —
|
|
470
503
|
known commands, ``--version``, ``--help``, zero-arg help — fall through to
|
|
471
504
|
the normal ``main()`` dispatch unchanged.
|
|
@@ -473,9 +506,9 @@ def _main_entrypoint() -> None:
|
|
|
473
506
|
argv = sys.argv[1:]
|
|
474
507
|
if argv and not argv[0].startswith("-") and argv[0] not in _KNOWN_COMMANDS:
|
|
475
508
|
print(f"{prog_name()}: error: unknown command '{argv[0]}'", file=sys.stderr)
|
|
476
|
-
# `
|
|
509
|
+
# `devex` here is the explain-topic identifier (topics/devex.md), not the
|
|
477
510
|
# invoked command name — the canonical "what is this tool" page.
|
|
478
|
-
stdout, _, _ = explain_script.run("
|
|
511
|
+
stdout, _, _ = explain_script.run("devex")
|
|
479
512
|
sys.stdout.write(stdout)
|
|
480
513
|
sys.exit(2)
|
|
481
514
|
sys.exit(main())
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: doctor
|
|
3
|
-
description: Diagnose the
|
|
3
|
+
description: Diagnose the devex install and the current project's `.devex/` state with a deterministic markdown health report.
|
|
4
4
|
type: command
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# `
|
|
7
|
+
# `devex doctor`
|
|
8
8
|
|
|
9
9
|
Run a zero-argument health check across:
|
|
10
10
|
|
|
11
|
-
1. **Install** — `
|
|
12
|
-
2. **Project state** — whether `.
|
|
11
|
+
1. **Install** — `devex` version, Python version, package resources are reachable.
|
|
12
|
+
2. **Project state** — whether `.devex/` exists in the current directory; if it does, that `config.toml` parses, `.gitignore` matches the managed content, and `data/` is writable.
|
|
13
13
|
3. **Internal consistency** — every shipped `commands/*/SKILL.md` parses with the required frontmatter, every per-backend capability YAML loads.
|
|
14
|
-
4. **Operator verification** — a short markdown checklist of things `doctor` cannot verify automatically (network reach, git-tracking of `.
|
|
14
|
+
4. **Operator verification** — a short markdown checklist of things `doctor` cannot verify automatically (network reach, git-tracking of `.devex/config.toml`, agent shell-tool wiring).
|
|
15
15
|
|
|
16
|
-
`doctor` is strictly read-only. It will never create `.
|
|
16
|
+
`doctor` is strictly read-only. It will never create `.devex/` or write anywhere on disk — if the directory is missing, that is reported as info and the command keeps going.
|
|
17
17
|
|
|
18
18
|
## Exit codes
|
|
19
19
|
|
|
@@ -26,8 +26,8 @@ Run a zero-argument health check across:
|
|
|
26
26
|
## From your shell tool
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
devex doctor # base health check
|
|
30
|
+
devex doctor --role pr-review # base + role-specific checks (when a role file ships)
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
## Role-specific checks
|
|
@@ -36,6 +36,6 @@ agex doctor --role pr-review # base + role-specific checks (when a role fil
|
|
|
36
36
|
|
|
37
37
|
## What `doctor` does *not* do
|
|
38
38
|
|
|
39
|
-
- It does not run backend probes — that's `
|
|
39
|
+
- It does not run backend probes — that's `devex overview --agent X`.
|
|
40
40
|
- It does not perform any auto-fix. Recovery instructions are emitted as markdown for the operator (agent or human) to act on.
|
|
41
41
|
- It does not touch the network.
|