atk-cli 0.2.0__tar.gz → 0.2.1__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.
- {atk_cli-0.2.0 → atk_cli-0.2.1}/PKG-INFO +1 -1
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/ROADMAP.md +5 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/backlog.md +2 -3
- atk_cli-0.2.1/docs/phases/phase-11-git-sync.md +88 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/commands-spec.md +37 -0
- atk_cli-0.2.1/docs/specs/git-sync-spec.md +156 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/home-spec.md +3 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/add.py +25 -7
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/cli.py +32 -4
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/status.py +55 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/git.py +218 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/init.py +1 -1
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/manifest_schema.py +4 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/remove.py +5 -2
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/upgrade.py +3 -1
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_add.py +48 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_git.py +303 -0
- atk_cli-0.2.1/tests/test_git_proxy.py +72 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_manifest_schema.py +19 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_mcp.py +2 -2
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_plug.py +0 -2
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_remove.py +47 -0
- atk_cli-0.2.1/tests/test_repo_status.py +109 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.github/pull_request_template.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.github/workflows/ci.yml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.github/workflows/publish.yml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/.gitignore +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/CODE_OF_CONDUCT.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/CONTRIBUTING.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/LICENSE +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/Makefile +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/README.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/SECURITY.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/demo-hero.gif +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/demo-search.gif +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/demo-status.gif +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/logo.png +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/tapes/demo-hero.tape +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/tapes/demo-search.tape +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/assets/tapes/demo-status.tape +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/README.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/legacy/backup-feature-spec.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/legacy/cli-architecture.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/legacy/service-yaml-spec.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/phases/phase-1-core-cli.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/phases/phase-2-lifecycle.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/phases/phase-3-configuration.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/phases/phase-4-plugin-sources.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/atk-spec.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/mcp-agent-configure-spec.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/plugin-schema.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/docs/specs/registry-spec.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/pyproject.toml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/skills/create-atk-plugin/SKILL.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/auggie_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/claude_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/codex_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/gemini_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/managed_section.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/opencode_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/agents/symlink_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/banner.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/bootstrap.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/cli_logger.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/lifecycle.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/mcp.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/plug.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/preconditions.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/run.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/search.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/commands/upgrade.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/env.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/errors.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/exit_codes.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/fetch.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/git_source.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/home.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/lifecycle.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/mcp.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/mcp_agents.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/mcp_configure.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/plugin.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/plugin_schema.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/registry.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/registry_schema.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/sanitize.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/setup.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/source.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/update_check.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/src/atk/validation.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_auggie_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_claude_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_codex_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_gemini_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_opencode_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/agents/test_symlink_skill.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/commands/__init__.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/commands/test_cli.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/commands/test_search.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/commands/test_status.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/conftest.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/README.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/SKILL.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/install.sh +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/mcp-server.sh +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/plugin.yaml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/start.sh +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/status.sh +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/full-plugin/stop.sh +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/invalid-plugin/plugin.yaml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/minimal-plugin/plugin.yaml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/skill-only-plugin/SKILL.md +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/fixtures/plugins/skill-only-plugin/plugin.yaml +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_env.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_errors.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_git_source.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_home.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_init.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_lifecycle.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_plugin.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_plugin_schema.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_registry.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_run.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_sanitize.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_setup.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_source.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_update_check.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_upgrade.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/tests/test_version.py +0 -0
- {atk_cli-0.2.0 → atk_cli-0.2.1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atk-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: AI Toolkit - Manage AI development tools through a git-backed, declarative manifest
|
|
5
5
|
Project-URL: Homepage, https://github.com/Svtoo/atk
|
|
6
6
|
Project-URL: Repository, https://github.com/Svtoo/atk
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
| 8 | MCP Management | ✅ | Auto-install to Claude Code, Codex, Gemini, etc. |
|
|
26
26
|
| 9 | Plug/Unplug | ✅ | `atk plug`/`unplug` — unified agent wiring |
|
|
27
27
|
| 10 | Data Backup | ⏳ | Backup/restore plugin data |
|
|
28
|
+
| 11 | Git Sync | 🔄 | Remote sync, auto-push, repo status |
|
|
28
29
|
|
|
29
30
|
## Phase Summaries
|
|
30
31
|
|
|
@@ -83,6 +84,10 @@ Deprecates `atk mcp add`/`atk mcp remove`. `atk mcp <plugin>` reverts to its ori
|
|
|
83
84
|
|
|
84
85
|
Backup and restore plugin data (databases, state files).
|
|
85
86
|
|
|
87
|
+
### Phase 11: Git Sync 🔄
|
|
88
|
+
|
|
89
|
+
`atk git` proxy command for managing the .atk repository without navigating to it. `auto_push` config parameter for automatic push after mutations. Enhanced `atk status` with repository section showing branch, remote, sync state, and working directory status.
|
|
90
|
+
|
|
86
91
|
---
|
|
87
92
|
|
|
88
93
|
## Navigation
|
|
@@ -8,10 +8,9 @@ This document collects ideas, deferred features, and future enhancements. Items
|
|
|
8
8
|
For the master plan, see `ROADMAP.md`.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## Git push
|
|
11
|
+
## ~~Git push~~ -> Promoted to Phase 11
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
also add command to pull changes from the remote. just a proxy for git, but useful so that the user does not need to navigate to the .atk directory to pull/push changes.
|
|
13
|
+
Addressed by Phase 11: Git Sync. `atk git` proxy command replaces dedicated push/pull commands. `auto_push` config parameter enables automatic push after mutations. `atk status` shows repository state. See `ROADMAP.md` Phase 11 and `specs/git-sync-spec.md`.
|
|
15
14
|
---
|
|
16
15
|
## ~~Manage Agents.md and other prompts through atk~~ → Promoted to Phase 9
|
|
17
16
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Phase 11: Git Sync
|
|
2
|
+
|
|
3
|
+
> **Status**: In Progress
|
|
4
|
+
> **Last Updated**: 2026-04-14
|
|
5
|
+
|
|
6
|
+
Remote synchronization for ATK Home. Users can add a git remote, auto-push after mutations, and see repository state in `atk status`.
|
|
7
|
+
|
|
8
|
+
## Goals
|
|
9
|
+
|
|
10
|
+
1. Users can manage the .atk git repo without navigating to the directory
|
|
11
|
+
2. Mutations can automatically push to a remote after committing
|
|
12
|
+
3. `atk status` shows the git repository state alongside plugin status
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Scenarios
|
|
17
|
+
|
|
18
|
+
### Scenario 1: Git Proxy
|
|
19
|
+
|
|
20
|
+
**User story:** I want to manage my .atk repo's git remote without `cd ~/.atk`.
|
|
21
|
+
|
|
22
|
+
**Flow:**
|
|
23
|
+
1. `atk git remote add origin git@github.com:user/dotfiles-atk.git`
|
|
24
|
+
2. ATK runs `git remote add origin ...` in ATK_HOME
|
|
25
|
+
3. Git output passed through to terminal
|
|
26
|
+
|
|
27
|
+
**Edge cases:**
|
|
28
|
+
- ATK Home not initialized -> exit 3
|
|
29
|
+
- Git not available -> exit 7
|
|
30
|
+
- Invalid git arguments -> git's own error, git's exit code
|
|
31
|
+
|
|
32
|
+
### Scenario 2: Auto-Push After Mutation
|
|
33
|
+
|
|
34
|
+
**User story:** I want my plugin changes to automatically sync to my remote.
|
|
35
|
+
|
|
36
|
+
**Flow:**
|
|
37
|
+
1. Edit `manifest.yaml` to set `auto_push: true`
|
|
38
|
+
2. `atk add openmemory`
|
|
39
|
+
3. ATK adds plugin, commits (auto_commit), pushes (auto_push)
|
|
40
|
+
4. Remote now has the latest state
|
|
41
|
+
|
|
42
|
+
**Edge cases:**
|
|
43
|
+
- No remote configured -> warn, don't error
|
|
44
|
+
- Push fails (auth, network) -> warn, don't error; commit already succeeded
|
|
45
|
+
- `auto_commit: false` with `auto_push: true` -> no push (push requires commit)
|
|
46
|
+
|
|
47
|
+
### Scenario 3: Repository Status
|
|
48
|
+
|
|
49
|
+
**User story:** I want to see if my .atk repo is in sync with the remote.
|
|
50
|
+
|
|
51
|
+
**Flow:**
|
|
52
|
+
1. `atk status`
|
|
53
|
+
2. ATK shows plugin table (existing behavior)
|
|
54
|
+
3. ATK shows Repository section: branch, remote, ahead/behind, last commit, working dir
|
|
55
|
+
|
|
56
|
+
**Edge cases:**
|
|
57
|
+
- No remote -> show `(none)` for remote, omit sync line
|
|
58
|
+
- No tracking branch -> show `(no tracking branch)` for sync
|
|
59
|
+
- Empty repo (no commits) -> gracefully degrade, show what's available
|
|
60
|
+
- Git queries fail -> skip failing fields, show what's available
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Tasks
|
|
65
|
+
|
|
66
|
+
- [ ] Write git-sync-spec.md
|
|
67
|
+
- [ ] Update ROADMAP.md with Phase 11
|
|
68
|
+
- [ ] Update commands-spec.md with `atk git` command
|
|
69
|
+
- [ ] Update home-spec.md with `auto_push` in manifest schema
|
|
70
|
+
- [ ] Update backlog.md — promote "Git push" item
|
|
71
|
+
- [ ] Add git helper functions to `git.py` (push, branch, remote info, ahead/behind, working dir status)
|
|
72
|
+
- [ ] Add `auto_push` field to `ConfigSection` in `manifest_schema.py`
|
|
73
|
+
- [ ] Add `atk git` proxy command to `cli.py`
|
|
74
|
+
- [ ] Add repository section to `atk status` output
|
|
75
|
+
- [ ] Wire auto-push into `add.py`, `remove.py`, `upgrade.py`
|
|
76
|
+
- [ ] Update initial manifest in `init.py` with `auto_push: false`
|
|
77
|
+
- [ ] Tests for all new functions and behaviors
|
|
78
|
+
|
|
79
|
+
## Acceptance Criteria
|
|
80
|
+
|
|
81
|
+
- `atk git remote add origin <url>` successfully adds a remote to .atk
|
|
82
|
+
- `atk git push` pushes .atk commits to the remote
|
|
83
|
+
- `atk git log --oneline` shows .atk commit history
|
|
84
|
+
- Setting `auto_push: true` in manifest causes mutations to push after commit
|
|
85
|
+
- Auto-push failure warns but does not fail the mutation
|
|
86
|
+
- `atk status` shows Repository section with branch, remote, sync, last commit, working dir
|
|
87
|
+
- `atk status` with no remote shows `(none)` gracefully
|
|
88
|
+
- `make check` passes (ruff + mypy + pytest)
|
|
@@ -62,6 +62,7 @@ flowchart TB
|
|
|
62
62
|
plug[atk plug]
|
|
63
63
|
mcp[atk mcp]
|
|
64
64
|
help[atk help]
|
|
65
|
+
git[atk git]
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
init --> add
|
|
@@ -711,6 +712,42 @@ Continue? [y/N]:
|
|
|
711
712
|
|
|
712
713
|
---
|
|
713
714
|
|
|
715
|
+
## `atk git [args...]`
|
|
716
|
+
|
|
717
|
+
Run git commands in ATK Home. Thin proxy — passes all arguments to `git` executed in ATK_HOME.
|
|
718
|
+
|
|
719
|
+
**Arguments:**
|
|
720
|
+
- `[args...]`: Any git arguments (passed through verbatim)
|
|
721
|
+
|
|
722
|
+
**Usage:**
|
|
723
|
+
```bash
|
|
724
|
+
atk git remote add origin git@github.com:user/dotfiles-atk.git
|
|
725
|
+
atk git remote show origin
|
|
726
|
+
atk git push
|
|
727
|
+
atk git pull
|
|
728
|
+
atk git log --oneline -5
|
|
729
|
+
atk git status
|
|
730
|
+
atk git diff
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**Behavior:**
|
|
734
|
+
1. Validate ATK Home is initialized (exit 3 if not)
|
|
735
|
+
2. Require git available (exit 7 if not)
|
|
736
|
+
3. Execute `git <args>` in ATK_HOME with stdin/stdout/stderr passed through
|
|
737
|
+
4. Return git's exit code
|
|
738
|
+
|
|
739
|
+
**Notes:**
|
|
740
|
+
- No argument validation — git handles its own errors
|
|
741
|
+
- Interactive commands work (stdin is passed through)
|
|
742
|
+
- Destructive commands are the user's responsibility
|
|
743
|
+
|
|
744
|
+
**Exit Codes:**
|
|
745
|
+
- 3: ATK Home not initialized
|
|
746
|
+
- 7: Git not available
|
|
747
|
+
- (other): Git's own exit code passed through
|
|
748
|
+
|
|
749
|
+
---
|
|
750
|
+
|
|
714
751
|
# Deferred to Future
|
|
715
752
|
|
|
716
753
|
The following commands and features are documented in `atk-future.md`:
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Git Sync Specification
|
|
2
|
+
|
|
3
|
+
> **Status**: Approved
|
|
4
|
+
> **Last Updated**: 2026-04-14
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
ATK Home is a git-backed repository. Phase 1 introduced `auto_commit` — every mutation creates a local commit. Git Sync extends this with remote synchronization: users can add a remote, auto-push after mutations, and see the repository state in `atk status`.
|
|
9
|
+
|
|
10
|
+
## Design Principles
|
|
11
|
+
|
|
12
|
+
1. **Proxy, don't reinvent.** `atk git` passes arguments straight to `git` in ATK_HOME. Users already know git.
|
|
13
|
+
2. **Push is best-effort.** Auto-push failures warn but never fail the mutation. The commit already succeeded locally.
|
|
14
|
+
3. **Sensible defaults.** `auto_push` defaults to `false`. Users opt in after adding a remote.
|
|
15
|
+
|
|
16
|
+
## `atk git [args...]`
|
|
17
|
+
|
|
18
|
+
Thin proxy that runs `git <args>` in ATK_HOME.
|
|
19
|
+
|
|
20
|
+
### Behavior
|
|
21
|
+
|
|
22
|
+
1. Resolve ATK_HOME (env var or `~/.atk/`)
|
|
23
|
+
2. Validate ATK Home is initialized (exit 3 if not)
|
|
24
|
+
3. Require git available (exit 7 if not)
|
|
25
|
+
4. Execute `git <args>` in ATK_HOME with stdin/stdout/stderr passed through (no capture)
|
|
26
|
+
5. Return git's exit code
|
|
27
|
+
|
|
28
|
+
### Examples
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
atk git remote add origin git@github.com:user/dotfiles-atk.git
|
|
32
|
+
atk git remote show origin
|
|
33
|
+
atk git push
|
|
34
|
+
atk git pull
|
|
35
|
+
atk git log --oneline -5
|
|
36
|
+
atk git status
|
|
37
|
+
atk git diff
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Edge Cases
|
|
41
|
+
|
|
42
|
+
- No arguments (`atk git`) — passes no args to git, which prints git help. Acceptable.
|
|
43
|
+
- Interactive commands (`atk git rebase -i`) — works because stdin/stdout are passed through.
|
|
44
|
+
- Destructive commands (`atk git reset --hard`) — user's responsibility. ATK does not guard against this.
|
|
45
|
+
|
|
46
|
+
## `auto_push` Configuration
|
|
47
|
+
|
|
48
|
+
New field in the manifest `config` section.
|
|
49
|
+
|
|
50
|
+
### Manifest Schema
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
config:
|
|
54
|
+
auto_commit: true # Existing (default: true)
|
|
55
|
+
auto_push: false # New (default: false)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Rules
|
|
59
|
+
|
|
60
|
+
| `auto_commit` | `auto_push` | Remote exists | Behavior |
|
|
61
|
+
|---------------|-------------|---------------|----------|
|
|
62
|
+
| true | true | yes | Commit + push |
|
|
63
|
+
| true | true | no | Commit only, warn "no remote configured" |
|
|
64
|
+
| true | false | any | Commit only (current behavior) |
|
|
65
|
+
| false | true | any | Neither — `auto_push` requires `auto_commit` |
|
|
66
|
+
| false | false | any | Neither (current behavior) |
|
|
67
|
+
|
|
68
|
+
### Push Semantics
|
|
69
|
+
|
|
70
|
+
- Pushes the current branch to its upstream tracking branch
|
|
71
|
+
- Command: `git push` (no force, no explicit remote/branch — uses git defaults)
|
|
72
|
+
- On failure: print warning to stderr, do not exit with error
|
|
73
|
+
- On success: silent (consistent with auto_commit behavior)
|
|
74
|
+
|
|
75
|
+
## Enhanced `atk status` — Repository Section
|
|
76
|
+
|
|
77
|
+
After the plugin status table, `atk status` displays a repository section.
|
|
78
|
+
|
|
79
|
+
### Output Format
|
|
80
|
+
|
|
81
|
+
**With remote:**
|
|
82
|
+
```
|
|
83
|
+
Repository:
|
|
84
|
+
Branch: main
|
|
85
|
+
Remote: origin -> git@github.com:user/dotfiles-atk.git
|
|
86
|
+
Sync: 2 ahead, 0 behind
|
|
87
|
+
Last commit: Add plugin 'sasha-rules' (2m ago)
|
|
88
|
+
Working dir: clean
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Without remote:**
|
|
92
|
+
```
|
|
93
|
+
Repository:
|
|
94
|
+
Branch: main
|
|
95
|
+
Remote: (none)
|
|
96
|
+
Last commit: Add plugin 'sasha-rules' (2m ago)
|
|
97
|
+
Working dir: clean
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**With dirty working directory:**
|
|
101
|
+
```
|
|
102
|
+
Repository:
|
|
103
|
+
Branch: main
|
|
104
|
+
Remote: origin -> git@github.com:user/dotfiles-atk.git
|
|
105
|
+
Sync: 0 ahead, 0 behind
|
|
106
|
+
Last commit: Initialize ATK Home (3d ago)
|
|
107
|
+
Working dir: 1 modified, 2 untracked
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**No remote tracking branch:**
|
|
111
|
+
```
|
|
112
|
+
Repository:
|
|
113
|
+
Branch: main
|
|
114
|
+
Remote: origin -> git@github.com:user/dotfiles-atk.git
|
|
115
|
+
Sync: (no tracking branch)
|
|
116
|
+
Last commit: Add plugin 'openmemory' (1h ago)
|
|
117
|
+
Working dir: clean
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Fields
|
|
121
|
+
|
|
122
|
+
| Field | Source | Notes |
|
|
123
|
+
|-------|--------|-------|
|
|
124
|
+
| Branch | `git branch --show-current` | Current branch name |
|
|
125
|
+
| Remote | `git remote get-url origin` | First remote name + URL. `(none)` if no remotes |
|
|
126
|
+
| Sync | `git rev-list --left-right --count HEAD...@{upstream}` | Ahead/behind upstream. Omitted if no remote. `(no tracking branch)` if remote exists but no tracking |
|
|
127
|
+
| Last commit | `git log -1 --format='%s (%cr)'` | Subject + relative time |
|
|
128
|
+
| Working dir | `git status --porcelain` | `clean` if empty, otherwise count by category |
|
|
129
|
+
|
|
130
|
+
### Error Handling
|
|
131
|
+
|
|
132
|
+
If any git query fails (e.g., empty repo with no commits), the Repository section gracefully degrades — show what's available, skip what's not.
|
|
133
|
+
|
|
134
|
+
## Auto-Push Wiring
|
|
135
|
+
|
|
136
|
+
Mutations that auto-commit (`add`, `remove`, `upgrade`) gain auto-push:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
mutation happens
|
|
140
|
+
-> if auto_commit:
|
|
141
|
+
git add -A
|
|
142
|
+
git commit -m "..."
|
|
143
|
+
-> if auto_push:
|
|
144
|
+
git push (best-effort, warn on failure)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Warning Messages
|
|
148
|
+
|
|
149
|
+
- No remote: `Warning: auto_push enabled but no remote configured. Run: atk git remote add origin <url>`
|
|
150
|
+
- Push failed: `Warning: auto-push failed: <git error message>`
|
|
151
|
+
|
|
152
|
+
## Exit Codes
|
|
153
|
+
|
|
154
|
+
`atk git` uses git's own exit codes (passed through). No new ATK exit codes needed.
|
|
155
|
+
|
|
156
|
+
For auto-push failures within mutations, the mutation still exits 0 (the commit succeeded).
|
|
@@ -96,6 +96,7 @@ schema_version: "2026-01-22"
|
|
|
96
96
|
|
|
97
97
|
config:
|
|
98
98
|
auto_commit: true # Commit after mutations (default: true)
|
|
99
|
+
auto_push: false # Push after auto-commit (default: false)
|
|
99
100
|
|
|
100
101
|
plugins:
|
|
101
102
|
- name: "OpenMemory" # Display name (user-friendly)
|
|
@@ -165,6 +166,8 @@ Display names (`name` field) have no restrictions—they are for human readabili
|
|
|
165
166
|
|
|
166
167
|
If `auto_commit: false`, user must manually commit changes.
|
|
167
168
|
|
|
169
|
+
If `auto_push: true` and `auto_commit: true` and a remote is configured, ATK pushes after each auto-commit. Push failures warn but do not fail the mutation. If no remote is configured, auto-push silently no-ops with a warning.
|
|
170
|
+
|
|
168
171
|
## User Customizations
|
|
169
172
|
|
|
170
173
|
Users customize plugins via the `custom/` directory inside each plugin.
|
|
@@ -10,11 +10,25 @@ from enum import Enum
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
import atk.registry as registry_mod
|
|
13
|
-
from atk.git import
|
|
13
|
+
from atk.git import (
|
|
14
|
+
add_gitignore_exemption,
|
|
15
|
+
git_add,
|
|
16
|
+
git_commit,
|
|
17
|
+
git_ls_remote,
|
|
18
|
+
git_push,
|
|
19
|
+
write_atk_ref,
|
|
20
|
+
)
|
|
14
21
|
from atk.git_source import fetch_git_plugin, normalize_git_url
|
|
15
22
|
from atk.home import validate_atk_home
|
|
16
23
|
from atk.lifecycle import LifecycleCommandNotDefinedError, run_lifecycle_command
|
|
17
|
-
from atk.manifest_schema import
|
|
24
|
+
from atk.manifest_schema import (
|
|
25
|
+
ConfigSection,
|
|
26
|
+
PluginEntry,
|
|
27
|
+
SourceInfo,
|
|
28
|
+
SourceType,
|
|
29
|
+
load_manifest,
|
|
30
|
+
save_manifest,
|
|
31
|
+
)
|
|
18
32
|
from atk.plugin import load_plugin_schema
|
|
19
33
|
from atk.plugin_schema import PluginMaturity, PluginSchema
|
|
20
34
|
from atk.sanitize import sanitize_directory_name
|
|
@@ -299,11 +313,13 @@ def _finalize_add(
|
|
|
299
313
|
if source.ref:
|
|
300
314
|
write_atk_ref(target_dir, source.ref)
|
|
301
315
|
|
|
302
|
-
|
|
316
|
+
config = _update_manifest(atk_home, schema.name, directory, source=source)
|
|
303
317
|
|
|
304
|
-
if auto_commit:
|
|
318
|
+
if config.auto_commit:
|
|
305
319
|
git_add(atk_home)
|
|
306
320
|
git_commit(atk_home, f"Add plugin '{schema.name}'")
|
|
321
|
+
if config.auto_push:
|
|
322
|
+
git_push(atk_home)
|
|
307
323
|
|
|
308
324
|
return directory
|
|
309
325
|
except Exception:
|
|
@@ -338,7 +354,9 @@ def _cleanup_failed_add(atk_home: Path, target_dir: Path, directory: str, alread
|
|
|
338
354
|
pass
|
|
339
355
|
|
|
340
356
|
|
|
341
|
-
def _update_manifest(
|
|
357
|
+
def _update_manifest(
|
|
358
|
+
atk_home: Path, plugin_name: str, directory: str, source: SourceInfo,
|
|
359
|
+
) -> ConfigSection:
|
|
342
360
|
"""Update manifest.yaml with new plugin entry.
|
|
343
361
|
|
|
344
362
|
Args:
|
|
@@ -348,7 +366,7 @@ def _update_manifest(atk_home: Path, plugin_name: str, directory: str, source: S
|
|
|
348
366
|
source: Source metadata (type, ref, url).
|
|
349
367
|
|
|
350
368
|
Returns:
|
|
351
|
-
|
|
369
|
+
The manifest's config section.
|
|
352
370
|
"""
|
|
353
371
|
manifest = load_manifest(atk_home)
|
|
354
372
|
|
|
@@ -358,7 +376,7 @@ def _update_manifest(atk_home: Path, plugin_name: str, directory: str, source: S
|
|
|
358
376
|
# Write back
|
|
359
377
|
save_manifest(manifest, atk_home)
|
|
360
378
|
|
|
361
|
-
return manifest.config
|
|
379
|
+
return manifest.config
|
|
362
380
|
|
|
363
381
|
|
|
364
382
|
|
|
@@ -13,6 +13,7 @@ from atk import __version__, cli_logger, exit_codes
|
|
|
13
13
|
from atk.add import AddCancelledError, InstallFailedError, add_plugin
|
|
14
14
|
from atk.banner import print_banner
|
|
15
15
|
from atk.commands.lifecycle import run_lifecycle_cli, run_restart_single_cli, run_uninstall_cli
|
|
16
|
+
from atk.commands.plug import plug_plugin, unplug_plugin
|
|
16
17
|
from atk.commands.preconditions import (
|
|
17
18
|
assert_plugin_or_all,
|
|
18
19
|
require_git,
|
|
@@ -21,10 +22,9 @@ from atk.commands.preconditions import (
|
|
|
21
22
|
require_ready_home,
|
|
22
23
|
stdin_prompt,
|
|
23
24
|
)
|
|
24
|
-
from atk.commands.plug import plug_plugin, unplug_plugin
|
|
25
25
|
from atk.commands.run import run_plugin_script
|
|
26
26
|
from atk.commands.search import filter_registry_plugins, print_search_table
|
|
27
|
-
from atk.commands.status import print_status_table
|
|
27
|
+
from atk.commands.status import print_repo_status, print_status_table
|
|
28
28
|
from atk.commands.upgrade import upgrade_all_plugins, upgrade_single_plugin
|
|
29
29
|
from atk.errors import handle_cli_error
|
|
30
30
|
from atk.git_source import GitPluginNotFoundError, GitSourceError
|
|
@@ -726,9 +726,10 @@ def status(
|
|
|
726
726
|
|
|
727
727
|
if not results:
|
|
728
728
|
cli_logger.dim("No plugins installed.")
|
|
729
|
-
|
|
729
|
+
else:
|
|
730
|
+
print_status_table(results)
|
|
730
731
|
|
|
731
|
-
|
|
732
|
+
print_repo_status(atk_home)
|
|
732
733
|
raise typer.Exit(exit_codes.SUCCESS)
|
|
733
734
|
|
|
734
735
|
|
|
@@ -815,6 +816,33 @@ def run(
|
|
|
815
816
|
run_plugin_script(plugin_dir, script, ctx.args)
|
|
816
817
|
|
|
817
818
|
|
|
819
|
+
@app.command(
|
|
820
|
+
name="git",
|
|
821
|
+
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
822
|
+
)
|
|
823
|
+
def git_proxy(ctx: typer.Context) -> None:
|
|
824
|
+
"""Run git commands in ATK Home.
|
|
825
|
+
|
|
826
|
+
Thin proxy that passes all arguments to git executed in the ATK Home
|
|
827
|
+
directory. Useful for managing remotes, pushing, pulling, and inspecting
|
|
828
|
+
the repository without navigating to it.
|
|
829
|
+
|
|
830
|
+
Examples:
|
|
831
|
+
atk git remote add origin <url>
|
|
832
|
+
atk git push
|
|
833
|
+
atk git log --oneline -5
|
|
834
|
+
"""
|
|
835
|
+
import subprocess
|
|
836
|
+
|
|
837
|
+
atk_home = require_ready_home()
|
|
838
|
+
|
|
839
|
+
result = subprocess.run(
|
|
840
|
+
["git", *ctx.args],
|
|
841
|
+
cwd=atk_home,
|
|
842
|
+
)
|
|
843
|
+
raise typer.Exit(result.returncode)
|
|
844
|
+
|
|
845
|
+
|
|
818
846
|
def _show_update_notice() -> None:
|
|
819
847
|
"""Show update notice if a newer version is available on PyPI.
|
|
820
848
|
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
"""Status table rendering for the `atk status` command."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
3
7
|
from rich.console import Console
|
|
4
8
|
from rich.table import Table
|
|
5
9
|
|
|
10
|
+
from atk.git import (
|
|
11
|
+
git_ahead_behind,
|
|
12
|
+
git_get_branch,
|
|
13
|
+
git_get_remote_url,
|
|
14
|
+
git_last_commit_info,
|
|
15
|
+
git_working_dir_status,
|
|
16
|
+
)
|
|
6
17
|
from atk.lifecycle import PluginStatus, PluginStatusResult, PortStatus
|
|
7
18
|
from atk.plugin_schema import PluginMaturity
|
|
8
19
|
|
|
@@ -121,3 +132,47 @@ def print_status_table(results: list[PluginStatusResult]) -> None:
|
|
|
121
132
|
"[dim]Note: Port checks verify if something is listening, not that it's the plugin.[/dim]"
|
|
122
133
|
)
|
|
123
134
|
|
|
135
|
+
|
|
136
|
+
def print_repo_status(atk_home: Path) -> None:
|
|
137
|
+
"""Print git repository status section after the plugin table."""
|
|
138
|
+
console.print()
|
|
139
|
+
console.print("[bold]Repository:[/bold]")
|
|
140
|
+
|
|
141
|
+
# Branch
|
|
142
|
+
branch = git_get_branch(atk_home)
|
|
143
|
+
branch_str = branch if branch else "(detached)"
|
|
144
|
+
console.print(f" Branch: {branch_str}")
|
|
145
|
+
|
|
146
|
+
# Remote
|
|
147
|
+
remote_info = git_get_remote_url(atk_home)
|
|
148
|
+
if remote_info:
|
|
149
|
+
remote_name, remote_url = remote_info
|
|
150
|
+
console.print(f" Remote: {remote_name} -> {remote_url}")
|
|
151
|
+
else:
|
|
152
|
+
console.print(" Remote: [dim](none)[/dim]")
|
|
153
|
+
|
|
154
|
+
# Sync (only if remote exists)
|
|
155
|
+
if remote_info:
|
|
156
|
+
ab = git_ahead_behind(atk_home)
|
|
157
|
+
if ab:
|
|
158
|
+
console.print(f" Sync: {ab.ahead} ahead, {ab.behind} behind")
|
|
159
|
+
else:
|
|
160
|
+
console.print(" Sync: [dim](no tracking branch)[/dim]")
|
|
161
|
+
|
|
162
|
+
# Last commit
|
|
163
|
+
commit = git_last_commit_info(atk_home)
|
|
164
|
+
if commit:
|
|
165
|
+
console.print(f" Last commit: {commit.subject} ({commit.relative_time})")
|
|
166
|
+
|
|
167
|
+
# Working directory
|
|
168
|
+
wd = git_working_dir_status(atk_home)
|
|
169
|
+
if wd.is_clean:
|
|
170
|
+
console.print(" Working dir: [green]clean[/green]")
|
|
171
|
+
else:
|
|
172
|
+
parts = []
|
|
173
|
+
if wd.modified:
|
|
174
|
+
parts.append(f"{wd.modified} modified")
|
|
175
|
+
if wd.untracked:
|
|
176
|
+
parts.append(f"{wd.untracked} untracked")
|
|
177
|
+
console.print(f" Working dir: [yellow]{', '.join(parts)}[/yellow]")
|
|
178
|
+
|