aisquare-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aisquare_cli-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- aisquare_cli-0.1.0/.github/dependabot.yml +17 -0
- aisquare_cli-0.1.0/.github/workflows/ci.yml +76 -0
- aisquare_cli-0.1.0/.github/workflows/publish.yml +42 -0
- aisquare_cli-0.1.0/.gitignore +22 -0
- aisquare_cli-0.1.0/CONTRIBUTING.md +68 -0
- aisquare_cli-0.1.0/LICENSE +21 -0
- aisquare_cli-0.1.0/Makefile +25 -0
- aisquare_cli-0.1.0/PKG-INFO +307 -0
- aisquare_cli-0.1.0/README.md +278 -0
- aisquare_cli-0.1.0/pyproject.toml +70 -0
- aisquare_cli-0.1.0/src/aisquare/__init__.py +10 -0
- aisquare_cli-0.1.0/src/aisquare/__main__.py +6 -0
- aisquare_cli-0.1.0/src/aisquare/cli/__init__.py +1 -0
- aisquare_cli-0.1.0/src/aisquare/cli/agents.py +60 -0
- aisquare_cli-0.1.0/src/aisquare/cli/app.py +101 -0
- aisquare_cli-0.1.0/src/aisquare/cli/auth.py +27 -0
- aisquare_cli-0.1.0/src/aisquare/cli/capture.py +39 -0
- aisquare_cli-0.1.0/src/aisquare/cli/common.py +350 -0
- aisquare_cli-0.1.0/src/aisquare/cli/config.py +54 -0
- aisquare_cli-0.1.0/src/aisquare/cli/connectors.py +37 -0
- aisquare_cli-0.1.0/src/aisquare/cli/context.py +139 -0
- aisquare_cli-0.1.0/src/aisquare/cli/enforce.py +27 -0
- aisquare_cli-0.1.0/src/aisquare/cli/hook.py +61 -0
- aisquare_cli-0.1.0/src/aisquare/cli/policy.py +15 -0
- aisquare_cli-0.1.0/src/aisquare/cli/project.py +66 -0
- aisquare_cli-0.1.0/src/aisquare/cli/root.py +158 -0
- aisquare_cli-0.1.0/src/aisquare/core/__init__.py +1 -0
- aisquare_cli-0.1.0/src/aisquare/core/agents.py +196 -0
- aisquare_cli-0.1.0/src/aisquare/core/config.py +63 -0
- aisquare_cli-0.1.0/src/aisquare/core/console.py +17 -0
- aisquare_cli-0.1.0/src/aisquare/core/editor.py +39 -0
- aisquare_cli-0.1.0/src/aisquare/core/entries.py +33 -0
- aisquare_cli-0.1.0/src/aisquare/core/ids.py +51 -0
- aisquare_cli-0.1.0/src/aisquare/core/injection.py +60 -0
- aisquare_cli-0.1.0/src/aisquare/core/paths.py +82 -0
- aisquare_cli-0.1.0/src/aisquare/core/snapshot.py +221 -0
- aisquare_cli-0.1.0/src/aisquare/core/state.py +35 -0
- aisquare_cli-0.1.0/src/aisquare/core/store.py +430 -0
- aisquare_cli-0.1.0/src/aisquare/core/stubs.py +34 -0
- aisquare_cli-0.1.0/src/aisquare/core/workspace.py +84 -0
- aisquare_cli-0.1.0/src/aisquare/models.py +167 -0
- aisquare_cli-0.1.0/src/aisquare/py.typed +0 -0
- aisquare_cli-0.1.0/src/aisquare/services/__init__.py +6 -0
- aisquare_cli-0.1.0/src/aisquare/services/agents.py +87 -0
- aisquare_cli-0.1.0/src/aisquare/services/auth.py +35 -0
- aisquare_cli-0.1.0/src/aisquare/services/capture.py +30 -0
- aisquare_cli-0.1.0/src/aisquare/services/connectors.py +25 -0
- aisquare_cli-0.1.0/src/aisquare/services/context.py +213 -0
- aisquare_cli-0.1.0/src/aisquare/services/diagnostics.py +193 -0
- aisquare_cli-0.1.0/src/aisquare/services/hooks.py +62 -0
- aisquare_cli-0.1.0/src/aisquare/services/lifecycle.py +93 -0
- aisquare_cli-0.1.0/src/aisquare/services/policy.py +25 -0
- aisquare_cli-0.1.0/src/aisquare/services/project.py +106 -0
- aisquare_cli-0.1.0/src/aisquare/services/settings.py +72 -0
- aisquare_cli-0.1.0/src/aisquare/services/sync.py +10 -0
- aisquare_cli-0.1.0/tests/__init__.py +1 -0
- aisquare_cli-0.1.0/tests/cli_tree.py +58 -0
- aisquare_cli-0.1.0/tests/conftest.py +49 -0
- aisquare_cli-0.1.0/tests/test_agents.py +127 -0
- aisquare_cli-0.1.0/tests/test_config.py +47 -0
- aisquare_cli-0.1.0/tests/test_context.py +309 -0
- aisquare_cli-0.1.0/tests/test_help.py +16 -0
- aisquare_cli-0.1.0/tests/test_hooks.py +78 -0
- aisquare_cli-0.1.0/tests/test_ids.py +31 -0
- aisquare_cli-0.1.0/tests/test_init.py +91 -0
- aisquare_cli-0.1.0/tests/test_injection.py +131 -0
- aisquare_cli-0.1.0/tests/test_json_mode.py +22 -0
- aisquare_cli-0.1.0/tests/test_packaging.py +11 -0
- aisquare_cli-0.1.0/tests/test_project.py +116 -0
- aisquare_cli-0.1.0/tests/test_settings.py +71 -0
- aisquare_cli-0.1.0/tests/test_snapshot.py +80 -0
- aisquare_cli-0.1.0/tests/test_status.py +81 -0
- aisquare_cli-0.1.0/tests/test_store.py +247 -0
- aisquare_cli-0.1.0/tests/test_stubs.py +88 -0
- aisquare_cli-0.1.0/tests/test_version.py +20 -0
- aisquare_cli-0.1.0/tests/test_workspace.py +72 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## What & why
|
|
2
|
+
|
|
3
|
+
<!-- What does this change do, and why? Link any related issue. -->
|
|
4
|
+
|
|
5
|
+
## How to verify
|
|
6
|
+
|
|
7
|
+
<!-- Commands run, behaviour observed. -->
|
|
8
|
+
|
|
9
|
+
## Checklist
|
|
10
|
+
|
|
11
|
+
- [ ] `make check` passes locally (lint + typecheck + tests)
|
|
12
|
+
- [ ] Added or updated tests for the change
|
|
13
|
+
- [ ] If a command graduated from stub to real, it's removed from the
|
|
14
|
+
`IMPLEMENTED` skip-list in `tests/test_stubs.py` and has its own tests
|
|
15
|
+
- [ ] Updated docs (README / CONTRIBUTING) if behaviour or commands changed
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Keep GitHub Actions pinned actions current.
|
|
4
|
+
- package-ecosystem: github-actions
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: weekly
|
|
8
|
+
commit-message:
|
|
9
|
+
prefix: ci
|
|
10
|
+
|
|
11
|
+
# Keep Python dependencies current.
|
|
12
|
+
- package-ecosystem: pip
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: weekly
|
|
16
|
+
commit-message:
|
|
17
|
+
prefix: deps
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
# Cancel superseded runs on the same branch/PR.
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
check:
|
|
19
|
+
name: check (py${{ matrix.python-version }})
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
|
|
28
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
29
|
+
uses: actions/setup-python@v6
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python-version }}
|
|
32
|
+
cache: pip
|
|
33
|
+
cache-dependency-path: pyproject.toml
|
|
34
|
+
|
|
35
|
+
- name: Install
|
|
36
|
+
run: |
|
|
37
|
+
python -m pip install --upgrade pip
|
|
38
|
+
pip install -e ".[dev]"
|
|
39
|
+
|
|
40
|
+
- name: Lint (ruff)
|
|
41
|
+
run: ruff check src tests
|
|
42
|
+
|
|
43
|
+
- name: Format check (ruff)
|
|
44
|
+
run: ruff format --check src tests
|
|
45
|
+
|
|
46
|
+
- name: Type check (mypy)
|
|
47
|
+
run: mypy
|
|
48
|
+
|
|
49
|
+
- name: Test (pytest)
|
|
50
|
+
run: pytest -ra
|
|
51
|
+
|
|
52
|
+
package:
|
|
53
|
+
name: package (build + install)
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v7
|
|
57
|
+
|
|
58
|
+
- name: Set up Python
|
|
59
|
+
uses: actions/setup-python@v6
|
|
60
|
+
with:
|
|
61
|
+
python-version: "3.12"
|
|
62
|
+
|
|
63
|
+
- name: Build sdist and wheel
|
|
64
|
+
run: |
|
|
65
|
+
python -m pip install --upgrade pip build
|
|
66
|
+
python -m build
|
|
67
|
+
|
|
68
|
+
- name: Install the wheel in a clean environment
|
|
69
|
+
run: |
|
|
70
|
+
python -m venv /tmp/smoke
|
|
71
|
+
/tmp/smoke/bin/pip install dist/*.whl
|
|
72
|
+
- name: Smoke-test the console scripts
|
|
73
|
+
run: |
|
|
74
|
+
/tmp/smoke/bin/aisquare --version
|
|
75
|
+
/tmp/smoke/bin/asq --version
|
|
76
|
+
/tmp/smoke/bin/aisquare --help
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI via Trusted Publishing (OIDC) — no API token/secret needed.
|
|
4
|
+
# Triggered when a GitHub Release is published. The version that ships is whatever
|
|
5
|
+
# is in pyproject.toml, so bump it before tagging the release.
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
name: Build sdist + wheel
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- name: Build
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade build
|
|
25
|
+
python -m build
|
|
26
|
+
- uses: actions/upload-artifact@v4
|
|
27
|
+
with:
|
|
28
|
+
name: dist
|
|
29
|
+
path: dist/
|
|
30
|
+
|
|
31
|
+
publish:
|
|
32
|
+
name: Publish to PyPI
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write # OIDC token for Trusted Publishing
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
|
|
8
|
+
# Environments
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
|
|
12
|
+
# Tooling caches
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# OS / editors
|
|
20
|
+
.DS_Store
|
|
21
|
+
.idea/
|
|
22
|
+
.vscode/
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Contributing to aisquare
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in aisquare! This is an early-stage, open-source
|
|
4
|
+
project and contributions are welcome.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
Requires Python 3.11+.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
python3 -m venv .venv
|
|
12
|
+
source .venv/bin/activate
|
|
13
|
+
make install # editable install + dev tools (ruff, mypy, pytest)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Before you open a PR
|
|
17
|
+
|
|
18
|
+
Run the full check suite — this is exactly what CI runs:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
make check # lint + typecheck + tests
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Individual targets:
|
|
25
|
+
|
|
26
|
+
| Task | Command |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| Format + autofix | `make fmt` |
|
|
29
|
+
| Lint | `make lint` |
|
|
30
|
+
| Type-check (mypy strict) | `make typecheck` |
|
|
31
|
+
| Tests | `make test` |
|
|
32
|
+
|
|
33
|
+
CI (`.github/workflows/ci.yml`) runs lint, format-check, mypy and pytest on
|
|
34
|
+
Python 3.11–3.13, plus a packaging job that builds the wheel and smoke-tests the
|
|
35
|
+
`aisquare` / `asq` console scripts. All jobs must pass before a PR can merge.
|
|
36
|
+
|
|
37
|
+
## Implementing a feature (stub → service)
|
|
38
|
+
|
|
39
|
+
Most commands are still stubs that exit `70`. Each one becomes real by replacing
|
|
40
|
+
a single `stub(...)` call in a `services/` module — the CLI wiring and function
|
|
41
|
+
signatures already exist. The flow is:
|
|
42
|
+
|
|
43
|
+
1. **Implement the service** in `src/aisquare/services/<domain>.py`. Services
|
|
44
|
+
return data; they never parse CLI arguments or print. Persisted state goes
|
|
45
|
+
through the `ContextStore` in `src/aisquare/core/store.py`.
|
|
46
|
+
2. **Render it** in the matching `src/aisquare/cli/<group>.py` command: parse,
|
|
47
|
+
call the service, print (honouring `--json` via `get_state().json_output`).
|
|
48
|
+
Shared rendering helpers live in `cli/common.py`.
|
|
49
|
+
3. **Move the command off the stub skip-list** in `tests/test_stubs.py`
|
|
50
|
+
(`IMPLEMENTED`) and add real tests for the new behaviour.
|
|
51
|
+
|
|
52
|
+
See the README's [Architecture](README.md#architecture) section for the full
|
|
53
|
+
layout and the thin-CLI / service / core split.
|
|
54
|
+
|
|
55
|
+
## Conventions
|
|
56
|
+
|
|
57
|
+
- **Type everything.** `mypy` runs in `strict` mode over `src` and `tests`.
|
|
58
|
+
- **Tests are isolated.** The `isolated_home` fixture points `AISQUARE_HOME` at
|
|
59
|
+
a temp dir, so tests never touch your real `~/.aisquare`. Never write to the
|
|
60
|
+
real home in a test or example.
|
|
61
|
+
- Keep CLI modules thin and services free of CLI concerns.
|
|
62
|
+
- New shared plumbing goes in `core/`; new domain shapes go in `models.py`.
|
|
63
|
+
|
|
64
|
+
## Reporting bugs / proposing features
|
|
65
|
+
|
|
66
|
+
Open an issue describing what you expected and what happened. For larger
|
|
67
|
+
changes, it's worth opening an issue to discuss the approach before writing
|
|
68
|
+
code.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AISquare
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.PHONY: install test lint typecheck fmt check
|
|
2
|
+
|
|
3
|
+
## install: editable install with dev tools (run inside a virtualenv)
|
|
4
|
+
install:
|
|
5
|
+
pip install -e ".[dev]"
|
|
6
|
+
|
|
7
|
+
## test: run the test suite
|
|
8
|
+
test:
|
|
9
|
+
pytest
|
|
10
|
+
|
|
11
|
+
## lint: static checks without modifying files
|
|
12
|
+
lint:
|
|
13
|
+
ruff check src tests
|
|
14
|
+
|
|
15
|
+
## typecheck: run mypy over src and tests
|
|
16
|
+
typecheck:
|
|
17
|
+
mypy
|
|
18
|
+
|
|
19
|
+
## fmt: auto-format and auto-fix lint findings
|
|
20
|
+
fmt:
|
|
21
|
+
ruff format src tests
|
|
22
|
+
ruff check --fix src tests
|
|
23
|
+
|
|
24
|
+
## check: everything CI would run
|
|
25
|
+
check: lint typecheck test
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aisquare-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Portable memory layer for coding agents — persistent user and project context across sessions.
|
|
5
|
+
Project-URL: Homepage, https://aisquare.studio
|
|
6
|
+
Project-URL: Repository, https://github.com/AISquare-Studio/aisquare-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/AISquare-Studio/aisquare-cli/issues
|
|
8
|
+
Author-email: AISquare <anmol@aisquare.studio>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,ai,cli,context,memory
|
|
12
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: pydantic>=2.13.4
|
|
21
|
+
Requires-Dist: rich>=13.7
|
|
22
|
+
Requires-Dist: tomli-w>=1.2.0
|
|
23
|
+
Requires-Dist: typer>=0.26.8
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=9.1.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# aisquare
|
|
31
|
+
|
|
32
|
+
**Portable memory layer for coding agents.** `aisquare` installs into agents
|
|
33
|
+
like Claude Code and keeps their context — your preferences and each project's
|
|
34
|
+
conventions — persistent across sessions and machines.
|
|
35
|
+
|
|
36
|
+
> **Status: early.** The full command surface exists and parses arguments.
|
|
37
|
+
> Implemented and backed by a local SQLite store: `init`, `remember`, the full
|
|
38
|
+
> `context` group, `inject`/`why`, the `project` group (incl. a **Repomix
|
|
39
|
+
> codebase snapshot**), `status`/`doctor`, the `config` group, `log`, and the
|
|
40
|
+
> `agents` group — which **installs into Claude Code** (see
|
|
41
|
+
> [Claude Code integration](#claude-code-integration)). The remaining commands
|
|
42
|
+
> (`auth`/cloud, `capture`, `sync`, `connectors`, `policy`) are stubs: each
|
|
43
|
+
> prints `⚠ aisquare <command> is not implemented yet (planned: <tier>)` to
|
|
44
|
+
> stderr and exits `70`. Features land one service module at a time — see
|
|
45
|
+
> [Implementing a feature](#implementing-a-feature-stub--service).
|
|
46
|
+
|
|
47
|
+
## Implemented
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
aisquare init # set up ~/.aisquare, register & onboard this project
|
|
51
|
+
aisquare remember "prefer pytest over unittest" --user --tag testing
|
|
52
|
+
aisquare context add "run make check before pushing" --project
|
|
53
|
+
aisquare context list # user pool + the active project's pool
|
|
54
|
+
aisquare context search pytest # full-text search (SQLite FTS5)
|
|
55
|
+
aisquare context show a3f2 # by id or unambiguous prefix (git-style)
|
|
56
|
+
aisquare context edit a3f2 # opens the entry in $EDITOR
|
|
57
|
+
aisquare context promote a3f2 # move a project entry into the user pool
|
|
58
|
+
aisquare context remove a3f2 # soft-delete (tombstoned)
|
|
59
|
+
aisquare context export out.md # export in-scope context (md or --format json)
|
|
60
|
+
aisquare context import notes.md # seed context from Markdown bullets or JSON
|
|
61
|
+
aisquare context preview # the context block that would be injected
|
|
62
|
+
aisquare inject # emit that block (and record the injection)
|
|
63
|
+
aisquare why # explain the last injection
|
|
64
|
+
aisquare project list # registered projects (active one marked *)
|
|
65
|
+
aisquare project switch alpha # pin the active project (name or id prefix)
|
|
66
|
+
aisquare project onboard # pack a Repomix snapshot + seed ecosystem facts
|
|
67
|
+
aisquare agents scan # detect installed agents (Claude Code, …)
|
|
68
|
+
aisquare agents connect claude-code # install hooks + ingest CLAUDE.md
|
|
69
|
+
aisquare log # captured prompt history for this project
|
|
70
|
+
aisquare status # health, pools, active project, agents
|
|
71
|
+
aisquare doctor # checks deps/install/hooks/snapshot + how to fix each
|
|
72
|
+
aisquare config set default_pool user # read/write config (get/list/redaction)
|
|
73
|
+
aisquare --json context list # machine-readable output (any command)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Context lives in two pools — `user` (global) and `project` — persisted in a
|
|
77
|
+
SQLite database at `~/.aisquare/context.db`. The **active project** is whichever
|
|
78
|
+
you `project switch` to (pinned in `state.json`), else the one containing your
|
|
79
|
+
working directory; everything scopes to it consistently. Entries carry
|
|
80
|
+
sync-ready metadata (`updated_at`, soft-delete tombstones) and time-sortable,
|
|
81
|
+
prefix-addressable ids from day one.
|
|
82
|
+
|
|
83
|
+
## Claude Code integration
|
|
84
|
+
|
|
85
|
+
`aisquare agents connect claude-code` makes aisquare an active part of Claude
|
|
86
|
+
Code by writing two hooks into `~/.claude/settings.json` (merged, never
|
|
87
|
+
clobbering your other settings; remove them with `agents disconnect`):
|
|
88
|
+
|
|
89
|
+
- **`SessionStart` → `aisquare hook session-start`** — injects a directive that
|
|
90
|
+
points Claude at the codebase snapshot (skeleton first, full pack on demand)
|
|
91
|
+
and the prompt history, plus your in-scope context — so Claude orients without
|
|
92
|
+
burning tokens grepping for files.
|
|
93
|
+
- **`UserPromptSubmit` → `aisquare hook user-prompt-submit`** — captures how you
|
|
94
|
+
prompt, so Claude can replay your intent (`aisquare log`).
|
|
95
|
+
|
|
96
|
+
The **codebase snapshot** (`project onboard`, or `init`) mirrors the server-side
|
|
97
|
+
[Repomix](https://github.com/yamadashy/repomix) packing for sync-consistency: a
|
|
98
|
+
full pack (`repomix --style xml`), a skeleton (`--compress`), and a per-file
|
|
99
|
+
index (char offsets + token counts), stored under
|
|
100
|
+
`~/.aisquare/projects/<id>/snapshot/`. Requires Node + repomix on PATH (run via
|
|
101
|
+
`npx` otherwise); if neither is present the snapshot is skipped, not fatal.
|
|
102
|
+
|
|
103
|
+
## Requirements
|
|
104
|
+
|
|
105
|
+
- Python 3.11+
|
|
106
|
+
- Optional, for codebase snapshots: Node.js + [repomix](https://github.com/yamadashy/repomix) (or it runs via `npx`)
|
|
107
|
+
|
|
108
|
+
## Install
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
pipx install aisquare-cli # recommended — isolated, stable `aisquare` / `asq` on PATH
|
|
112
|
+
# or: pip install aisquare-cli
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Installs two equivalent commands: `aisquare` and `asq`. The PyPI distribution is
|
|
116
|
+
**`aisquare-cli`** (the `aisquare` name belongs to the AISquare SDK); the command
|
|
117
|
+
stays `aisquare`. `pipx` is recommended so the Claude Code hook keeps a stable
|
|
118
|
+
path. Run `aisquare doctor` to see what's set up and what's missing.
|
|
119
|
+
|
|
120
|
+
## Install (development)
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
python3 -m venv .venv
|
|
124
|
+
source .venv/bin/activate
|
|
125
|
+
make install # = pip install -e ".[dev]"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Quick check
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
aisquare --help
|
|
132
|
+
aisquare --version
|
|
133
|
+
aisquare doctor # install/deps/integration health
|
|
134
|
+
asq ctx list # aliases work too
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Command tree
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
aisquare
|
|
141
|
+
├── init [path] [--api-key K] [--local] [--agent A]... [--no-onboard] [--reinit] [-y]
|
|
142
|
+
├── status · doctor · inject · sync · why · log · open
|
|
143
|
+
├── remember <text> [--user|--project] [--tag T]...
|
|
144
|
+
├── login · logout · whoami · upgrade · uninstall
|
|
145
|
+
├── auth status · rotate · token
|
|
146
|
+
├── agents list · connect <name> · disconnect <name> · scan · status [name]
|
|
147
|
+
├── connectors list · add <name> · remove <name> · status
|
|
148
|
+
├── context list · add <text> [--user|--project] [--tag T]... · show <id> · edit <id>
|
|
149
|
+
│ (alias ctx) remove <id> · search <query> · preview · import <file>
|
|
150
|
+
│ export [file] [--format md|json] · promote <id>
|
|
151
|
+
├── project info · list · switch <name> · link <repo> · onboard [path] [--refresh]
|
|
152
|
+
│ (alias workspace)
|
|
153
|
+
├── capture status · pause · resume · start · stop
|
|
154
|
+
├── config list · get <key> · set <key> <value> · redaction <off|standard|strict>
|
|
155
|
+
├── policy list
|
|
156
|
+
└── enforce status · enable · disable
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Global flags
|
|
160
|
+
|
|
161
|
+
| Flag | Meaning |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| `-V`, `--version` | Print the version and exit |
|
|
164
|
+
| `-v`, `--verbose` | Verbose output |
|
|
165
|
+
| `-q`, `--quiet` | Suppress non-essential output |
|
|
166
|
+
| `--json` | Machine-readable JSON on stdout |
|
|
167
|
+
| `--profile NAME` | Configuration profile to use |
|
|
168
|
+
| `--no-color` | Disable coloured output |
|
|
169
|
+
|
|
170
|
+
Global flags go **before** the command: `aisquare --json context list`.
|
|
171
|
+
|
|
172
|
+
### Exit codes
|
|
173
|
+
|
|
174
|
+
| Code | Meaning |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `0` | Success |
|
|
177
|
+
| `2` | Usage error (bad arguments) |
|
|
178
|
+
| `70` | Command not implemented yet |
|
|
179
|
+
|
|
180
|
+
## Architecture
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
src/aisquare/
|
|
184
|
+
├── cli/ # THIN Typer layer: one module per command group.
|
|
185
|
+
│ │ # Parses arguments, then calls exactly one service function.
|
|
186
|
+
│ ├── app.py # root app: global flags, --version, group registration
|
|
187
|
+
│ ├── root.py # top-level commands (init, status, remember, ...)
|
|
188
|
+
│ ├── common.py # shared parsing helpers (e.g. --user/--project → pool)
|
|
189
|
+
│ └── <group>.py
|
|
190
|
+
├── services/ # SERVICE layer: one module per domain. Real behaviour goes
|
|
191
|
+
│ │ # here. Today every function raises the shared stub.
|
|
192
|
+
│ └── <domain>.py
|
|
193
|
+
├── core/ # shared infrastructure (already real):
|
|
194
|
+
│ ├── paths.py # ~/.aisquare layout (override with $AISQUARE_HOME)
|
|
195
|
+
│ ├── config.py # typed TOML config load/save (Pydantic + tomllib/tomli-w)
|
|
196
|
+
│ ├── store.py # SQLite context store (ContextStore protocol + open_store)
|
|
197
|
+
│ ├── ids.py # ULID-style, time-sortable, prefix-addressable entry ids
|
|
198
|
+
│ ├── entries.py# shared ContextEntry factory (add / import / onboard)
|
|
199
|
+
│ ├── workspace.py # resolve the active project (pin in state.json, else cwd)
|
|
200
|
+
│ ├── injection.py # assemble the context block + record injections (why)
|
|
201
|
+
│ ├── agents.py # detect agents + install Claude Code hooks (settings.json)
|
|
202
|
+
│ ├── snapshot.py # Repomix codebase pack (full + skeleton + index)
|
|
203
|
+
│ ├── editor.py # launch $EDITOR for `context edit`
|
|
204
|
+
│ ├── state.py # runtime state from the global flags
|
|
205
|
+
│ ├── console.py# Rich console factories honouring --no-color
|
|
206
|
+
│ └── stubs.py # stub() — the consistent not-implemented behaviour
|
|
207
|
+
└── models.py # Pydantic domain models (ContextEntry, DataEnvelope, ...)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Flow: `cli/<group>.py` parses arguments → calls `services/<domain>.py` →
|
|
211
|
+
(today) `core/stubs.py:stub()` prints the not-implemented message and raises
|
|
212
|
+
`typer.Exit(70)`.
|
|
213
|
+
|
|
214
|
+
**What is real today:** `--help` everywhere, `--version`, global-flag parsing
|
|
215
|
+
into `core/state.py`, the `~/.aisquare/` layout, TOML config load/save, the
|
|
216
|
+
SQLite context store (`core/store.py`), and the commands wired to it — `init`,
|
|
217
|
+
`remember`, the full `context` group (`add`, `list`, `show`, `edit`, `remove`,
|
|
218
|
+
`search`, `promote`, `import`, `export`, `preview`), `inject`, `why`, the
|
|
219
|
+
`project` group (`info`, `list`, `switch`, `link`, `onboard`+snapshot),
|
|
220
|
+
`status`, `doctor`, the `config` group (`list`, `get`, `set`, `redaction`),
|
|
221
|
+
`log`, and the `agents` group (`scan`, `list`, `status`, `connect`+hooks,
|
|
222
|
+
`disconnect`). Everything else is a stub.
|
|
223
|
+
|
|
224
|
+
### `~/.aisquare/` layout
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
~/.aisquare/
|
|
228
|
+
├── config.toml # typed configuration (core/config.py)
|
|
229
|
+
├── credentials # API keys / tokens
|
|
230
|
+
├── context.db # SQLite store: context entries, projects, captured prompts
|
|
231
|
+
├── state.json # small runtime state (e.g. the pinned active project)
|
|
232
|
+
├── agents.json # registry of connected agents
|
|
233
|
+
├── projects/ # per-project data — <id>/snapshot/ (Repomix pack + skeleton + index)
|
|
234
|
+
├── cache/ # disposable cached data (e.g. last_injection.json)
|
|
235
|
+
└── log/ # capture and diagnostic logs
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Set `AISQUARE_HOME` to relocate the whole tree (the test suite does this).
|
|
239
|
+
|
|
240
|
+
## Implementing a feature (stub → service)
|
|
241
|
+
|
|
242
|
+
Each feature is implemented by replacing one `stub(...)` call in one service
|
|
243
|
+
module. The CLI wiring, argument parsing and signatures already exist. Example —
|
|
244
|
+
making `aisquare context add` real:
|
|
245
|
+
|
|
246
|
+
**1. Implement the service** (`src/aisquare/services/context.py`). Replace the
|
|
247
|
+
stub with real logic; keep the existing signature, it is already final.
|
|
248
|
+
Persisted state goes through the `ContextStore` from `core/store.py`. The
|
|
249
|
+
already-implemented `add_entry` is the worked example:
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
def add_entry(text: str, pool: Pool | None, tags: list[str]) -> ContextEntry:
|
|
253
|
+
"""Add a context entry to the user or project pool."""
|
|
254
|
+
resolved: Pool = pool or load_config().default_pool
|
|
255
|
+
with store_session() as store:
|
|
256
|
+
project_id: str | None = None
|
|
257
|
+
if resolved == "project":
|
|
258
|
+
project = current_project()
|
|
259
|
+
store.ensure_project(project)
|
|
260
|
+
project_id = project.id
|
|
261
|
+
now = datetime.now(tz=UTC)
|
|
262
|
+
entry = ContextEntry(
|
|
263
|
+
id=new_entry_id(), pool=resolved, project_id=project_id, text=text,
|
|
264
|
+
tags=tags, source="cli", created_at=now, updated_at=now,
|
|
265
|
+
)
|
|
266
|
+
return store.add(entry)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**2. Render in the CLI layer** (`src/aisquare/cli/context.py`). The CLI module
|
|
270
|
+
stays thin: parse, call the service, print. Honour `--json` via the runtime
|
|
271
|
+
state:
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
@app.command("add")
|
|
275
|
+
def add(text: ..., user: ..., project: ..., tag: ...) -> None:
|
|
276
|
+
"""Add a context entry."""
|
|
277
|
+
entry = context_service.add_entry(text, pool=resolve_pool(user, project), tags=tag or [])
|
|
278
|
+
if get_state().json_output:
|
|
279
|
+
typer.echo(entry.model_dump_json())
|
|
280
|
+
else:
|
|
281
|
+
stdout_console().print(f"✓ remembered ({entry.pool}): {entry.text}")
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**3. Update the tests.** The walk-based test in `tests/test_stubs.py` asserts
|
|
285
|
+
that every leaf exits with `70`; once a command is real it will fail there —
|
|
286
|
+
add the command to an explicit "implemented" skip-list in that test and write
|
|
287
|
+
real tests for the new behaviour.
|
|
288
|
+
|
|
289
|
+
Rules of thumb:
|
|
290
|
+
|
|
291
|
+
- CLI modules never contain behaviour; services never parse CLI arguments.
|
|
292
|
+
- Services return data; the CLI renders it. (`stub()` printing is the one
|
|
293
|
+
deliberate exception, so all unimplemented commands behave identically.)
|
|
294
|
+
- New shared plumbing goes in `core/`; new domain shapes go in `models.py`.
|
|
295
|
+
|
|
296
|
+
## Development
|
|
297
|
+
|
|
298
|
+
| Task | Command |
|
|
299
|
+
| --- | --- |
|
|
300
|
+
| Install (editable + dev tools) | `make install` |
|
|
301
|
+
| Run tests | `make test` |
|
|
302
|
+
| Lint | `make lint` |
|
|
303
|
+
| Type-check | `make typecheck` |
|
|
304
|
+
| Format + autofix | `make fmt` |
|
|
305
|
+
| All CI checks | `make check` |
|
|
306
|
+
|
|
307
|
+
Run a single test: `pytest tests/test_stubs.py -k "context add"`.
|