kscli 1.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.
Files changed (73) hide show
  1. kscli-1.1.0/.github/workflows/workflow.yml +180 -0
  2. kscli-1.1.0/.gitignore +207 -0
  3. kscli-1.1.0/.pre-commit-config.yaml +16 -0
  4. kscli-1.1.0/.serena/.gitignore +1 -0
  5. kscli-1.1.0/.serena/memories/project_overview.md +64 -0
  6. kscli-1.1.0/.serena/memories/style_and_conventions.md +32 -0
  7. kscli-1.1.0/.serena/memories/suggested_commands.md +44 -0
  8. kscli-1.1.0/.serena/memories/task_completion_checklist.md +15 -0
  9. kscli-1.1.0/.serena/project.yml +117 -0
  10. kscli-1.1.0/CHANGELOG.md +23 -0
  11. kscli-1.1.0/CLAUDE.md +84 -0
  12. kscli-1.1.0/LICENSE +21 -0
  13. kscli-1.1.0/Makefile +49 -0
  14. kscli-1.1.0/PKG-INFO +203 -0
  15. kscli-1.1.0/README.md +186 -0
  16. kscli-1.1.0/docs/authentication.md +147 -0
  17. kscli-1.1.0/docs/ci.md +102 -0
  18. kscli-1.1.0/docs/configuration.md +135 -0
  19. kscli-1.1.0/docs/design_patterns.md +120 -0
  20. kscli-1.1.0/docs/e2e-testing.md +165 -0
  21. kscli-1.1.0/kscli.code-workspace +93 -0
  22. kscli-1.1.0/pyproject.toml +65 -0
  23. kscli-1.1.0/ruff.toml +120 -0
  24. kscli-1.1.0/semantic_release.toml +87 -0
  25. kscli-1.1.0/src/kscli/__init__.py +0 -0
  26. kscli-1.1.0/src/kscli/__main__.py +3 -0
  27. kscli-1.1.0/src/kscli/auth.py +85 -0
  28. kscli-1.1.0/src/kscli/cli.py +140 -0
  29. kscli-1.1.0/src/kscli/client.py +109 -0
  30. kscli-1.1.0/src/kscli/commands/__init__.py +0 -0
  31. kscli-1.1.0/src/kscli/commands/auth.py +41 -0
  32. kscli-1.1.0/src/kscli/commands/chunk_lineages.py +58 -0
  33. kscli-1.1.0/src/kscli/commands/chunks.py +133 -0
  34. kscli-1.1.0/src/kscli/commands/document_versions.py +118 -0
  35. kscli-1.1.0/src/kscli/commands/documents.py +149 -0
  36. kscli-1.1.0/src/kscli/commands/folders.py +148 -0
  37. kscli-1.1.0/src/kscli/commands/invites.py +75 -0
  38. kscli-1.1.0/src/kscli/commands/path_parts.py +48 -0
  39. kscli-1.1.0/src/kscli/commands/permissions.py +93 -0
  40. kscli-1.1.0/src/kscli/commands/sections.py +82 -0
  41. kscli-1.1.0/src/kscli/commands/settings.py +77 -0
  42. kscli-1.1.0/src/kscli/commands/tags.py +123 -0
  43. kscli-1.1.0/src/kscli/commands/tenants.py +102 -0
  44. kscli-1.1.0/src/kscli/commands/thread_messages.py +60 -0
  45. kscli-1.1.0/src/kscli/commands/threads.py +91 -0
  46. kscli-1.1.0/src/kscli/commands/users.py +26 -0
  47. kscli-1.1.0/src/kscli/commands/workflows.py +63 -0
  48. kscli-1.1.0/src/kscli/config.py +102 -0
  49. kscli-1.1.0/src/kscli/output.py +291 -0
  50. kscli-1.1.0/tests/__init__.py +0 -0
  51. kscli-1.1.0/tests/e2e/__init__.py +0 -0
  52. kscli-1.1.0/tests/e2e/cli_helpers.py +127 -0
  53. kscli-1.1.0/tests/e2e/conftest.py +181 -0
  54. kscli-1.1.0/tests/e2e/test_cli_auth.py +65 -0
  55. kscli-1.1.0/tests/e2e/test_cli_chunk_lineages.py +108 -0
  56. kscli-1.1.0/tests/e2e/test_cli_chunks.py +181 -0
  57. kscli-1.1.0/tests/e2e/test_cli_document_versions.py +160 -0
  58. kscli-1.1.0/tests/e2e/test_cli_documents.py +217 -0
  59. kscli-1.1.0/tests/e2e/test_cli_errors.py +47 -0
  60. kscli-1.1.0/tests/e2e/test_cli_folders.py +209 -0
  61. kscli-1.1.0/tests/e2e/test_cli_invites.py +45 -0
  62. kscli-1.1.0/tests/e2e/test_cli_output_formats.py +83 -0
  63. kscli-1.1.0/tests/e2e/test_cli_path_parts.py +44 -0
  64. kscli-1.1.0/tests/e2e/test_cli_permissions.py +77 -0
  65. kscli-1.1.0/tests/e2e/test_cli_sections.py +104 -0
  66. kscli-1.1.0/tests/e2e/test_cli_settings.py +53 -0
  67. kscli-1.1.0/tests/e2e/test_cli_tags.py +179 -0
  68. kscli-1.1.0/tests/e2e/test_cli_tenants.py +51 -0
  69. kscli-1.1.0/tests/e2e/test_cli_thread_messages.py +111 -0
  70. kscli-1.1.0/tests/e2e/test_cli_threads.py +110 -0
  71. kscli-1.1.0/tests/e2e/test_cli_users.py +24 -0
  72. kscli-1.1.0/tests/e2e/test_cli_workflows.py +26 -0
  73. kscli-1.1.0/uv.lock +462 -0
@@ -0,0 +1,180 @@
1
+ name: Test
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ if: github.event_name == 'pull_request' || !startsWith(github.event.head_commit.message, 'chore(release):')
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v6
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v5
20
+ with:
21
+ version: "latest"
22
+ enable-cache: true
23
+ cache-dependency-glob: "uv.lock"
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.14"
29
+
30
+ - name: Cache virtual environment
31
+ uses: actions/cache@v4
32
+ id: cache-venv
33
+ with:
34
+ path: .venv
35
+ key: venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
36
+ restore-keys: |
37
+ venv-${{ runner.os }}-
38
+
39
+ - name: Install dev dependencies
40
+ run: uv sync --all-extras --group dev
41
+
42
+ - name: Run ruff check
43
+ run: make lint
44
+
45
+ - name: Run type checker
46
+ run: make typecheck
47
+
48
+ e2e:
49
+ runs-on: ubuntu-latest
50
+ if: github.event_name == 'pull_request' || !startsWith(github.event.head_commit.message, 'chore(release):')
51
+ steps:
52
+ - name: Generate GitHub App token
53
+ uses: actions/create-github-app-token@v1
54
+ id: app-token
55
+ with:
56
+ app-id: ${{ secrets.RELEASE_GH_APP_ID }}
57
+ private-key: ${{ secrets.RELEASE_GH_APP_PRIVATE_KEY }}
58
+ owner: ${{ github.repository_owner }}
59
+ repositories: ks-backend
60
+
61
+ - name: Checkout ks-cli
62
+ uses: actions/checkout@v6
63
+ with:
64
+ path: ks-cli
65
+
66
+ - name: Checkout ks-backend
67
+ uses: actions/checkout@v6
68
+ with:
69
+ repository: knowledgestack/ks-backend
70
+ token: ${{ steps.app-token.outputs.token }}
71
+ path: ks-backend
72
+
73
+ - name: Install uv
74
+ uses: astral-sh/setup-uv@v5
75
+ with:
76
+ version: "latest"
77
+ enable-cache: true
78
+ cache-dependency-glob: |
79
+ ks-backend/uv.lock
80
+ ks-cli/uv.lock
81
+
82
+ - name: Set up Python
83
+ uses: actions/setup-python@v5
84
+ with:
85
+ python-version: "3.14"
86
+
87
+ - name: Install ks-backend dependencies
88
+ working-directory: ks-backend
89
+ run: make install-dev
90
+
91
+ - name: Create shared email directory
92
+ run: mkdir -p /tmp/ks/e2e-testing/emails && chmod 777 /tmp/ks/e2e-testing/emails
93
+
94
+ - name: Start e2e stack
95
+ working-directory: ks-backend
96
+ run: make e2e-stack
97
+
98
+ - name: Seed database
99
+ working-directory: ks-backend
100
+ run: make e2e-prep
101
+
102
+ - name: Install ks-cli dependencies
103
+ working-directory: ks-cli
104
+ run: uv sync --all-extras --group dev
105
+
106
+ - name: Run e2e tests
107
+ working-directory: ks-cli
108
+ run: make e2e-test
109
+
110
+ release:
111
+ runs-on: ubuntu-latest
112
+ environment: "production"
113
+ concurrency:
114
+ group: release
115
+ cancel-in-progress: false
116
+ needs: [lint, e2e]
117
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
118
+ permissions:
119
+ contents: write
120
+ id-token: write
121
+ steps:
122
+ - name: Generate release token
123
+ uses: actions/create-github-app-token@v1
124
+ id: app-token
125
+ with:
126
+ app-id: ${{ secrets.RELEASE_GH_APP_ID }}
127
+ private-key: ${{ secrets.RELEASE_GH_APP_PRIVATE_KEY }}
128
+
129
+ - uses: actions/checkout@v6
130
+ with:
131
+ ref: main
132
+ token: ${{ steps.app-token.outputs.token }}
133
+ persist-credentials: true
134
+ fetch-depth: 0
135
+
136
+ - name: Setup | Install uv
137
+ uses: astral-sh/setup-uv@v5
138
+ with:
139
+ version: "latest"
140
+ enable-cache: true
141
+ cache-dependency-glob: "uv.lock"
142
+
143
+ - name: Set up Python
144
+ uses: actions/setup-python@v5
145
+ with:
146
+ python-version: "3.14"
147
+
148
+ - name: Install dev dependencies
149
+ run: uv sync
150
+
151
+ - name: Get current version
152
+ id: current-version
153
+ run: |
154
+ REPO_VERSION=$(uv version --short)
155
+ echo "Detected current version=${REPO_VERSION}"
156
+ echo "prevtag=v${REPO_VERSION}" >> $GITHUB_OUTPUT
157
+
158
+ # Don't use the official python-semantic-release action because it's too slow
159
+ - name: Run semantic-release
160
+ id: semantic-release
161
+ env:
162
+ GH_TOKEN: ${{ steps.app-token.outputs.token }} # For release publishing
163
+ run: |
164
+ uvx python-semantic-release -c semantic_release.toml version --vcs-release --changelog
165
+ NEW_TAG=$(uvx python-semantic-release -c semantic_release.toml version --print-tag)
166
+ echo "Current semantic release tag=${NEW_TAG}"
167
+ echo "tag=$NEW_TAG" >> $GITHUB_OUTPUT
168
+
169
+ - name: Check for build artifacts
170
+ id: check-dist
171
+ run: |
172
+ if ls dist/*.whl dist/*.tar.gz 1>/dev/null 2>&1; then
173
+ echo "has_dist=true" >> $GITHUB_OUTPUT
174
+ else
175
+ echo "has_dist=false" >> $GITHUB_OUTPUT
176
+ fi
177
+
178
+ - name: Publish to PyPI
179
+ if: steps.check-dist.outputs.has_dist == 'true'
180
+ uses: pypa/gh-action-pypi-publish@release/v1
kscli-1.1.0/.gitignore ADDED
@@ -0,0 +1,207 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ #.idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
@@ -0,0 +1,16 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: lint_fix
5
+ name: ruff check --fix
6
+ entry: make fix
7
+ language: system
8
+ pass_filenames: false
9
+ always_run: true
10
+
11
+ - id: typecheck
12
+ name: basedpyright typecheck
13
+ entry: make typecheck
14
+ language: system
15
+ pass_filenames: false
16
+ always_run: true
@@ -0,0 +1 @@
1
+ /cache
@@ -0,0 +1,64 @@
1
+ # Project Overview
2
+
3
+ ## Purpose
4
+ `ks-cli` (kscli) is a CLI tool for the Knowledge Stack platform. It wraps the auto-generated `ksapi` Python SDK with a Click-based command interface using a verb-first routing pattern (e.g. `kscli get folders`, `kscli describe document <id>`).
5
+
6
+ ## Tech Stack
7
+ - **Language**: Python 3.14+
8
+ - **Runtime/Package Manager**: uv
9
+ - **CLI Framework**: Click
10
+ - **HTTP Client**: httpx (for auth), ksapi SDK (generated, uses urllib3)
11
+ - **Output**: Rich (tables), custom formatters (json, yaml, tree, id-only)
12
+ - **Auth**: JWT-based via admin impersonation (`/v1/auth/assume_user`)
13
+ - **Linting**: Ruff
14
+ - **Type Checking**: basedpyright
15
+ - **Testing**: pytest (e2e tests via subprocess)
16
+ - **Releases**: semantic-release with conventional commits
17
+
18
+ ## Codebase Structure
19
+ ```
20
+ src/kscli/
21
+ ├── cli.py # Root CLI group, verb-first routing, command registration
22
+ ├── client.py # SDK client helpers (get_api_client, handle_client_errors, to_dict)
23
+ ├── auth.py # Credential caching, JWT token management, assume_user
24
+ ├── config.py # Layered config: env vars → config file → defaults
25
+ ├── output.py # Output formatters: table, json, yaml, id-only, tree
26
+ ├── __main__.py # Entry point
27
+ └── commands/
28
+ ├── auth.py # assume-user, whoami
29
+ ├── settings.py # settings environment, settings show
30
+ ├── folders.py # Folder CRUD
31
+ ├── documents.py # Document CRUD + ingest
32
+ ├── versions.py # Version CRUD + contents
33
+ ├── sections.py # Section CRUD
34
+ ├── chunks.py # Chunk CRUD + search
35
+ ├── chunk_lineages.py
36
+ ├── path_parts.py # Read-only
37
+ ├── tags.py # Tag CRUD + attach/detach
38
+ ├── tenants.py # Tenant CRUD + user listing
39
+ ├── invites.py # Invite CRUD + accept
40
+ ├── permissions.py # Permission CRUD
41
+ ├── threads.py # Thread/message CRUD
42
+ └── workflows.py # Workflow listing + actions
43
+
44
+ tests/
45
+ ├── conftest.py # Fixtures (cli_env, cli_authenticated)
46
+ ├── cli_helpers.py # Subprocess helpers (run_kscli, run_kscli_ok, run_kscli_fail)
47
+ └── test_cli_*.py # E2e tests per resource
48
+ ```
49
+
50
+ ## Key Architecture Patterns
51
+
52
+ ### Verb-first CLI routing
53
+ Commands are organized as `kscli <verb> <resource>`. Verb groups (get, describe, create, update, delete, search, etc.) are defined in `cli.py`. Each resource module exposes `register_<verb>(group)` functions that add Click commands to those groups.
54
+
55
+ ### Command implementation pattern
56
+ Every command follows this pattern:
57
+ 1. Get authenticated client: `api_client = get_api_client(ctx)`
58
+ 2. Wrap in error handling: `with handle_client_errors():`
59
+ 3. Instantiate SDK API: `api = ksapi.<Resource>Api(api_client)`
60
+ 4. Call SDK method and format: `print_result(ctx, to_dict(result), columns=COLUMNS)`
61
+
62
+ ### Config layering
63
+ Environment variables → `~/.config/kscli/config.json` → defaults.
64
+ Key env vars: `KSCLI_BASE_URL`, `ADMIN_API_KEY`, `KSCLI_FORMAT`, `KSCLI_VERIFY_SSL`, `KSCLI_CA_BUNDLE`, `KSCLI_CONFIG`, `KSCLI_CREDENTIALS_PATH`.
@@ -0,0 +1,32 @@
1
+ # Style and Conventions
2
+
3
+ ## Code Style
4
+ - **Line length**: 88 characters
5
+ - **Quote style**: Double quotes
6
+ - **Indent style**: Spaces
7
+ - **Docstrings**: Google convention (when present; most D1xx rules are ignored)
8
+ - **Type hints**: Used throughout; checked with basedpyright
9
+ - **Imports**: isort-managed, first-party packages: `shared_utils`, `database_schema`, `private_api_client`
10
+
11
+ ## Ruff Rules
12
+ Extensive rule set enabled (E, W, F, I, UP, B, C4, DTZ, T10, G, PIE, PT, RET, SIM, TCH, ARG, PTH, ERA, PD, PGH, PL, RUF, D). Notable ignores:
13
+ - All missing docstring rules (D100-D107) are ignored
14
+ - E501 (line length) ignored — handled by formatter
15
+ - B008 (function call in default argument) ignored — common in Click/FastAPI
16
+ - Tests allow assert, unused args (fixtures), magic values
17
+
18
+ ## Naming Conventions
19
+ - Command modules: `src/kscli/commands/<resource>.py`
20
+ - Test files: `tests/test_cli_<resource>.py`
21
+ - Registration functions: `register_<verb>(group: click.Group)`
22
+ - Column definitions: `COLUMNS = [...]` at module level
23
+
24
+ ## Design Patterns
25
+ - **Verb-first routing**: Commands registered as `<verb> <resource>`, not `<resource> <verb>`
26
+ - **Registration pattern**: Each module exposes `register_<verb>()` functions, wired in `cli.py`
27
+ - **Error handling**: Always use `with handle_client_errors():` context manager around API calls
28
+ - **SDK usage**: `ksapi` is auto-generated — never modify it directly
29
+ - **Output**: Always pass through `to_dict()` → `print_result()` pipeline
30
+
31
+ ## Commit Convention
32
+ Conventional commits (semantic-release): `feat:`, `fix:`, `perf:`, `chore:`, `ci:`, `docs:`, `style:`, `refactor:`, `test:`
@@ -0,0 +1,44 @@
1
+ # Suggested Commands
2
+
3
+ ## Development Setup
4
+ ```bash
5
+ uv sync --all-extras --group dev # Install all dependencies
6
+ uv run pre-commit install # Install pre-commit hooks
7
+ ```
8
+
9
+ ## Linting & Formatting
10
+ ```bash
11
+ uv run ruff check # Lint
12
+ uv run ruff check --fix # Lint + autofix
13
+ uv run ruff format # Format code
14
+ ```
15
+
16
+ ## Type Checking
17
+ ```bash
18
+ uv run basedpyright --stats # Type check
19
+ ```
20
+
21
+ ## Testing
22
+ ```bash
23
+ uv run pytest # Run all tests
24
+ uv run pytest tests/test_cli_folders.py # Single test file
25
+ uv run pytest tests/test_cli_folders.py::TestCliFolders::test_get_folders_root # Single test
26
+ uv run pytest -x # Stop on first failure
27
+ ```
28
+
29
+ ## Pre-commit (all checks)
30
+ ```bash
31
+ make pre-commit # Runs lint + typecheck + test
32
+ ```
33
+
34
+ ## Running the CLI
35
+ ```bash
36
+ uv run kscli --help # Show CLI help
37
+ uv run python -m kscli # Alternative entry point
38
+ ```
39
+
40
+ ## System utilities (macOS/Darwin)
41
+ ```bash
42
+ git status / git diff / git log # Git operations
43
+ ls / find / grep # File operations (standard unix)
44
+ ```
@@ -0,0 +1,15 @@
1
+ # Task Completion Checklist
2
+
3
+ After completing a coding task, run these checks:
4
+
5
+ 1. **Lint**: `uv run ruff check` — fix any issues with `uv run ruff check --fix`
6
+ 2. **Format**: `uv run ruff format` — ensure code is properly formatted
7
+ 3. **Type check**: `uv run basedpyright --stats` — resolve any type errors
8
+ 4. **Test**: `uv run pytest` — ensure all tests pass
9
+
10
+ Or run all at once: `make pre-commit`
11
+
12
+ ## When adding a new resource command
13
+ - Create `src/kscli/commands/<resource>.py` with `register_<verb>()` functions
14
+ - Register the commands in `src/kscli/cli.py` on the appropriate verb groups
15
+ - Add tests in `tests/test_cli_<resource>.py` using `cli_helpers.run_kscli_ok`/`run_kscli_fail`
@@ -0,0 +1,117 @@
1
+ # the name by which the project can be referenced within Serena
2
+ project_name: "ks-cli"
3
+
4
+
5
+ # list of languages for which language servers are started; choose from:
6
+ # al bash clojure cpp csharp
7
+ # csharp_omnisharp dart elixir elm erlang
8
+ # fortran fsharp go groovy haskell
9
+ # java julia kotlin lua markdown
10
+ # matlab nix pascal perl php
11
+ # php_phpactor powershell python python_jedi r
12
+ # rego ruby ruby_solargraph rust scala
13
+ # swift terraform toml typescript typescript_vts
14
+ # vue yaml zig
15
+ # (This list may be outdated. For the current list, see values of Language enum here:
16
+ # https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
17
+ # For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
18
+ # Note:
19
+ # - For C, use cpp
20
+ # - For JavaScript, use typescript
21
+ # - For Free Pascal/Lazarus, use pascal
22
+ # Special requirements:
23
+ # Some languages require additional setup/installations.
24
+ # See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
25
+ # When using multiple languages, the first language server that supports a given file will be used for that file.
26
+ # The first language is the default language and the respective language server will be used as a fallback.
27
+ # Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
28
+ languages:
29
+ - python
30
+
31
+ # the encoding used by text files in the project
32
+ # For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
33
+ encoding: "utf-8"
34
+
35
+ # whether to use project's .gitignore files to ignore files
36
+ ignore_all_files_in_gitignore: true
37
+
38
+ # list of additional paths to ignore in this project.
39
+ # Same syntax as gitignore, so you can use * and **.
40
+ # Note: global ignored_paths from serena_config.yml are also applied additively.
41
+ ignored_paths: []
42
+
43
+ # whether the project is in read-only mode
44
+ # If set to true, all editing tools will be disabled and attempts to use them will result in an error
45
+ # Added on 2025-04-18
46
+ read_only: false
47
+
48
+ # list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
49
+ # Below is the complete list of tools for convenience.
50
+ # To make sure you have the latest list of tools, and to view their descriptions,
51
+ # execute `uv run scripts/print_tool_overview.py`.
52
+ #
53
+ # * `activate_project`: Activates a project by name.
54
+ # * `check_onboarding_performed`: Checks whether project onboarding was already performed.
55
+ # * `create_text_file`: Creates/overwrites a file in the project directory.
56
+ # * `delete_lines`: Deletes a range of lines within a file.
57
+ # * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
58
+ # * `execute_shell_command`: Executes a shell command.
59
+ # * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
60
+ # * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
61
+ # * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
62
+ # * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
63
+ # * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
64
+ # * `initial_instructions`: Gets the initial instructions for the current project.
65
+ # Should only be used in settings where the system prompt cannot be set,
66
+ # e.g. in clients you have no control over, like Claude Desktop.
67
+ # * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
68
+ # * `insert_at_line`: Inserts content at a given line in a file.
69
+ # * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
70
+ # * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
71
+ # * `list_memories`: Lists memories in Serena's project-specific memory store.
72
+ # * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
73
+ # * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
74
+ # * `read_file`: Reads a file within the project directory.
75
+ # * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
76
+ # * `remove_project`: Removes a project from the Serena configuration.
77
+ # * `replace_lines`: Replaces a range of lines within a file with new content.
78
+ # * `replace_symbol_body`: Replaces the full definition of a symbol.
79
+ # * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
80
+ # * `search_for_pattern`: Performs a search for a pattern in the project.
81
+ # * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
82
+ # * `switch_modes`: Activates modes by providing a list of their names
83
+ # * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
84
+ # * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
85
+ # * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
86
+ # * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
87
+ excluded_tools: []
88
+
89
+ # list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default)
90
+ included_optional_tools: []
91
+
92
+ # fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
93
+ # This cannot be combined with non-empty excluded_tools or included_optional_tools.
94
+ fixed_tools: []
95
+
96
+ # list of mode names to that are always to be included in the set of active modes
97
+ # The full set of modes to be activated is base_modes + default_modes.
98
+ # If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
99
+ # Otherwise, this setting overrides the global configuration.
100
+ # Set this to [] to disable base modes for this project.
101
+ # Set this to a list of mode names to always include the respective modes for this project.
102
+ base_modes:
103
+
104
+ # list of mode names that are to be activated by default.
105
+ # The full set of modes to be activated is base_modes + default_modes.
106
+ # If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
107
+ # Otherwise, this overrides the setting from the global configuration (serena_config.yml).
108
+ # This setting can, in turn, be overridden by CLI parameters (--mode).
109
+ default_modes:
110
+
111
+ # initial prompt for the project. It will always be given to the LLM upon activating the project
112
+ # (contrary to the memories, which are loaded on demand).
113
+ initial_prompt: ""
114
+
115
+ # override of the corresponding setting in serena_config.yml, see the documentation there.
116
+ # If null or missing, the value from the global config is used.
117
+ symbol_info_budget: