nextcloud-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.
- nextcloud_cli-0.1.0/.github/workflows/publish.yml +33 -0
- nextcloud_cli-0.1.0/.github/workflows/release.yml +45 -0
- nextcloud_cli-0.1.0/.gitignore +23 -0
- nextcloud_cli-0.1.0/LICENSE +21 -0
- nextcloud_cli-0.1.0/PKG-INFO +282 -0
- nextcloud_cli-0.1.0/README.md +242 -0
- nextcloud_cli-0.1.0/pyproject.toml +71 -0
- nextcloud_cli-0.1.0/scripts/lint.sh +7 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/VERSION.md +1 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/__init__.py +3 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/__main__.py +4 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/cli.py +36 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/client.py +44 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/__init__.py +0 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/calendar.py +442 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/check.py +69 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/contacts.py +266 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/files.py +166 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/notes.py +119 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/setup.py +66 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/commands/tasks.py +250 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/config.py +151 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/rendering.py +262 -0
- nextcloud_cli-0.1.0/src/nextcloud_cli/utils.py +129 -0
- nextcloud_cli-0.1.0/tests/__init__.py +0 -0
- nextcloud_cli-0.1.0/tests/test_cli.py +39 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
release:
|
|
6
|
+
types:
|
|
7
|
+
- created
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
steps:
|
|
15
|
+
- name: Github actions init
|
|
16
|
+
uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
# To force fetching tags
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11"
|
|
25
|
+
|
|
26
|
+
- name: Install build dependencies
|
|
27
|
+
run: pip install build
|
|
28
|
+
|
|
29
|
+
- name: Build distribution
|
|
30
|
+
run: python -m build
|
|
31
|
+
|
|
32
|
+
- name: Publish
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Github actions init
|
|
14
|
+
uses: actions/checkout@v6
|
|
15
|
+
with:
|
|
16
|
+
# To force fetching tags
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v6
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.11"
|
|
23
|
+
|
|
24
|
+
- name: Install build dependencies
|
|
25
|
+
run: pip install build
|
|
26
|
+
|
|
27
|
+
- name: Build
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Read VERSION file
|
|
31
|
+
id: getversion
|
|
32
|
+
run: echo "version=$(cat src/nextcloud_cli/VERSION.md)" >> $GITHUB_OUTPUT
|
|
33
|
+
|
|
34
|
+
- name: Changelog
|
|
35
|
+
run: git log $(git describe --tags --abbrev=0)..HEAD --format="%s %h" > LATEST-CHANGES.md
|
|
36
|
+
|
|
37
|
+
- name: Release
|
|
38
|
+
uses: softprops/action-gh-release@v2
|
|
39
|
+
with:
|
|
40
|
+
files: |
|
|
41
|
+
dist/nextcloud_cli-${{ steps.getversion.outputs.version }}-py3-none-any.whl
|
|
42
|
+
dist/nextcloud_cli-${{ steps.getversion.outputs.version }}.tar.gz
|
|
43
|
+
tag_name: v${{ steps.getversion.outputs.version }}
|
|
44
|
+
body_path: LATEST-CHANGES.md
|
|
45
|
+
token: ${{ secrets.PAT_NXCLOUD }}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
*.egg
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
.env
|
|
19
|
+
.env.local
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
*.swp
|
|
23
|
+
.DS_Store
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alexandre
|
|
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,282 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nextcloud-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Modern command-line client for Nextcloud (files, notes, calendar, tasks, contacts)
|
|
5
|
+
Project-URL: Homepage, https://github.com/AlexMili/nextcloud-cli
|
|
6
|
+
Project-URL: Issues, https://github.com/AlexMili/nextcloud-cli/issues
|
|
7
|
+
Project-URL: Source, https://github.com/AlexMili/nextcloud-cli
|
|
8
|
+
Author: AlexMili
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: caldav,carddav,cli,nextcloud,webdav
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Communications :: File Sharing
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: caldav>=1.3
|
|
25
|
+
Requires-Dist: click>=8.1
|
|
26
|
+
Requires-Dist: httpx>=0.27
|
|
27
|
+
Requires-Dist: icalendar>=5.0
|
|
28
|
+
Requires-Dist: keyring>=24.0
|
|
29
|
+
Requires-Dist: python-dateutil>=2.8
|
|
30
|
+
Requires-Dist: rich>=13.0
|
|
31
|
+
Requires-Dist: tzlocal>=5.0
|
|
32
|
+
Requires-Dist: vobject>=0.9.7
|
|
33
|
+
Requires-Dist: webdav4>=0.10
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-mock>=3.10; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# nextcloud-cli
|
|
42
|
+
|
|
43
|
+
`nxcloud` is a modern command-line client for self-hosted Nextcloud. Manage
|
|
44
|
+
files, notes, calendar events, tasks, and contacts from the terminal — over
|
|
45
|
+
HTTPS only, no desktop sync client required.
|
|
46
|
+
|
|
47
|
+
It speaks WebDAV via [`webdav4`](https://pypi.org/project/webdav4/), CalDAV
|
|
48
|
+
via [`caldav`](https://pypi.org/project/caldav/), CardDAV via raw `httpx` +
|
|
49
|
+
[`vobject`](https://pypi.org/project/vobject/), and the Nextcloud Notes REST
|
|
50
|
+
API via `httpx`. Credentials are stored in your OS keyring.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Files** — list, upload, download, move, delete, mkdir, recursive search
|
|
55
|
+
- **Notes** — create, read, update, delete (Nextcloud Notes app required)
|
|
56
|
+
- **Calendar** — list calendars, list/create/edit/delete events, **with attendees and organizer**
|
|
57
|
+
- **Tasks** — list/create/complete/edit/delete VTODO items
|
|
58
|
+
- **Contacts** — list address books, list/get/export vCards
|
|
59
|
+
- **Login wizard** that validates the credentials with a `PROPFIND` and stores the password in the OS keyring (with a `chmod 0600` JSON fallback)
|
|
60
|
+
- **JSON output everywhere** so you can pipe into `jq` and friends
|
|
61
|
+
- `-h` / `--help` available on every command and subcommand
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install nextcloud-cli
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or from source:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/AlexMili/nextcloud-cli
|
|
73
|
+
cd nextcloud-cli
|
|
74
|
+
pip install -e .
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The installed binary is **`nxcloud`**.
|
|
78
|
+
|
|
79
|
+
## Login
|
|
80
|
+
|
|
81
|
+
Create a Nextcloud **app password** first
|
|
82
|
+
(`Settings → Security → App passwords`), then:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
nxcloud login
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
You'll only be prompted for what's missing. Values are resolved in this order:
|
|
89
|
+
|
|
90
|
+
1. CLI flag (`--url`, `--username`, `--password`, `--timezone`)
|
|
91
|
+
2. Environment variable (`NEXTCLOUD_URL`, `NEXTCLOUD_USER`, `NEXTCLOUD_TOKEN`, `NEXTCLOUD_TIMEZONE`)
|
|
92
|
+
3. Interactive prompt
|
|
93
|
+
|
|
94
|
+
So all of these work:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Fully interactive
|
|
98
|
+
nxcloud login
|
|
99
|
+
|
|
100
|
+
# Mixed: URL from env, prompt for the rest
|
|
101
|
+
NEXTCLOUD_URL=https://nc.example.com nxcloud login
|
|
102
|
+
|
|
103
|
+
# Fully non-interactive (no prompts)
|
|
104
|
+
nxcloud login \
|
|
105
|
+
--url https://nc.example.com \
|
|
106
|
+
--username alice \
|
|
107
|
+
--password 'app-pass-here' \
|
|
108
|
+
--timezone Europe/Paris
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
You can also skip persistence entirely and rely on environment variables for
|
|
112
|
+
every command:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
export NEXTCLOUD_URL=https://nc.example.com
|
|
116
|
+
export NEXTCLOUD_USER=alice
|
|
117
|
+
export NEXTCLOUD_TOKEN=app-pass-here
|
|
118
|
+
export NEXTCLOUD_TIMEZONE=Europe/Paris
|
|
119
|
+
nxcloud check
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To remove stored credentials:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
nxcloud logout
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Usage
|
|
129
|
+
|
|
130
|
+
Every command emits JSON on stdout for easy scripting. Use `-h` on any
|
|
131
|
+
command or subcommand for built-in help.
|
|
132
|
+
|
|
133
|
+
### Connectivity check
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
nxcloud check
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Files
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
nxcloud files list --path /Documents
|
|
143
|
+
nxcloud files upload --local ./report.pdf --remote /Documents/report.pdf
|
|
144
|
+
nxcloud files download --remote /Documents/report.pdf --local ./report.pdf
|
|
145
|
+
nxcloud files move --src /tmp/a.txt --dst /archive/a.txt
|
|
146
|
+
nxcloud files mkdir --path /new-folder
|
|
147
|
+
nxcloud files delete --path /old.txt
|
|
148
|
+
nxcloud files search --query report --limit 20 # OCS unified search (server-side)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Notes (requires the Nextcloud Notes app)
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
nxcloud notes list
|
|
155
|
+
nxcloud notes list --category Work # notes in the "Work" folder
|
|
156
|
+
nxcloud notes list --category "Work/Projects" # nested folder (subdirectory)
|
|
157
|
+
nxcloud notes list --category="" # only notes at the Notes/ root (no category)
|
|
158
|
+
nxcloud notes list --limit 10 # cap the number of notes fetched
|
|
159
|
+
nxcloud notes get --id 941
|
|
160
|
+
nxcloud notes create --title "Meeting" --content "Q3 roadmap." --category Work
|
|
161
|
+
nxcloud notes edit --id 941 --title "Updated"
|
|
162
|
+
nxcloud notes delete --id 941
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
> In the Nextcloud Notes app, **category = folder**: notes are stored as
|
|
166
|
+
> Markdown files under `Notes/<category>/`, and `/` separates subdirectories.
|
|
167
|
+
> `--category` matches **exactly** — `--category Work` does not include
|
|
168
|
+
> `Work/Projects`. Use `--category=""` to list only notes at the root.
|
|
169
|
+
|
|
170
|
+
### Calendar
|
|
171
|
+
|
|
172
|
+
List calendars and events:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
nxcloud calendar list
|
|
176
|
+
nxcloud calendar events --calendar Personal --start 2026-05-01 --end 2026-05-31
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Date-range shortcuts (server-side filtering, in your configured timezone):
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
nxcloud calendar events --calendar Personal --today
|
|
183
|
+
nxcloud calendar events --calendar Personal --this-week # current Mon → Mon
|
|
184
|
+
nxcloud calendar events --calendar Personal --next-week # upcoming Mon → Mon
|
|
185
|
+
nxcloud calendar events --calendar Personal --this-month # 1st → 1st of next month
|
|
186
|
+
nxcloud calendar events --calendar Personal --next-month
|
|
187
|
+
nxcloud calendar events --calendar Personal --next 7d # also: 48h, 2w
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
> Shortcuts are mutually exclusive with each other and with `--start/--end`.
|
|
191
|
+
|
|
192
|
+
Create an event with attendees and an organizer:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
nxcloud calendar create \
|
|
196
|
+
--calendar Work \
|
|
197
|
+
--summary "Project sync" \
|
|
198
|
+
--start 2026-07-01T14:00:00 \
|
|
199
|
+
--end 2026-07-01T15:00:00 \
|
|
200
|
+
--location "Room 4B" \
|
|
201
|
+
--description "Quarterly review" \
|
|
202
|
+
--organizer "Alice <alice@example.com>" \
|
|
203
|
+
--attendee "Bob <bob@example.com>" \
|
|
204
|
+
--attendee carol@example.com
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`--attendee` is repeatable and accepts either a bare email or the
|
|
208
|
+
`Name <email>` form.
|
|
209
|
+
|
|
210
|
+
Edit an event (including adding/removing invitees):
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
nxcloud calendar edit --calendar Work --uid <uid> --summary "New title"
|
|
214
|
+
nxcloud calendar edit --calendar Work --uid <uid> \
|
|
215
|
+
--add-attendee "Dan <dan@example.com>" \
|
|
216
|
+
--remove-attendee carol@example.com
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Delete an event:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
nxcloud calendar delete --calendar Work --uid <uid>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Search events server-side (CalDAV `text-match`). Combine with date filters:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
nxcloud calendar search --calendar Work --query standup
|
|
229
|
+
nxcloud calendar search --calendar Work --query roadmap --in description
|
|
230
|
+
nxcloud calendar search --calendar Work --query "1:1" --this-week
|
|
231
|
+
# --in: summary | description | location | category | all (default: summary)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Tasks (VTODO)
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
nxcloud tasks list
|
|
238
|
+
nxcloud tasks list --include-completed
|
|
239
|
+
nxcloud tasks create --summary "Review PR" --due 2026-07-05 --priority 1
|
|
240
|
+
nxcloud tasks complete --uid <uid>
|
|
241
|
+
nxcloud tasks edit --uid <uid> --summary "Updated summary"
|
|
242
|
+
nxcloud tasks delete --uid <uid>
|
|
243
|
+
nxcloud tasks search --query "deploy" --include-completed
|
|
244
|
+
nxcloud tasks search --query "fix" --in description --list Work
|
|
245
|
+
# --in: summary | description | category | all (default: summary)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Contacts
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
nxcloud contacts list
|
|
252
|
+
nxcloud contacts cards --addressbook contacts
|
|
253
|
+
nxcloud contacts get --addressbook contacts --uid <uid>
|
|
254
|
+
nxcloud contacts export --addressbook contacts --uid <uid> --local ./alice.vcf
|
|
255
|
+
nxcloud contacts search --addressbook contacts --query alex
|
|
256
|
+
nxcloud contacts search --addressbook contacts --query "@example.com" --in email
|
|
257
|
+
# --in: name | email | phone | all (default: all)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Configuration files
|
|
261
|
+
|
|
262
|
+
| File | Purpose | Permissions |
|
|
263
|
+
|------|---------|-------------|
|
|
264
|
+
| `~/.config/nextcloud-cli/config.json` | URL, username, timezone | `0600` |
|
|
265
|
+
| OS keyring (entry `nextcloud-cli`) | App password | OS-managed |
|
|
266
|
+
| `~/.config/nextcloud-cli/secrets.json` | Password fallback when no keyring backend is available | `0600` |
|
|
267
|
+
|
|
268
|
+
Override the config directory with the `NEXTCLOUD_CLI_HOME` environment variable.
|
|
269
|
+
|
|
270
|
+
## Help
|
|
271
|
+
|
|
272
|
+
`-h` and `--help` are wired up at every level:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
nxcloud --help
|
|
276
|
+
nxcloud calendar --help
|
|
277
|
+
nxcloud calendar create --help
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# nextcloud-cli
|
|
2
|
+
|
|
3
|
+
`nxcloud` is a modern command-line client for self-hosted Nextcloud. Manage
|
|
4
|
+
files, notes, calendar events, tasks, and contacts from the terminal — over
|
|
5
|
+
HTTPS only, no desktop sync client required.
|
|
6
|
+
|
|
7
|
+
It speaks WebDAV via [`webdav4`](https://pypi.org/project/webdav4/), CalDAV
|
|
8
|
+
via [`caldav`](https://pypi.org/project/caldav/), CardDAV via raw `httpx` +
|
|
9
|
+
[`vobject`](https://pypi.org/project/vobject/), and the Nextcloud Notes REST
|
|
10
|
+
API via `httpx`. Credentials are stored in your OS keyring.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Files** — list, upload, download, move, delete, mkdir, recursive search
|
|
15
|
+
- **Notes** — create, read, update, delete (Nextcloud Notes app required)
|
|
16
|
+
- **Calendar** — list calendars, list/create/edit/delete events, **with attendees and organizer**
|
|
17
|
+
- **Tasks** — list/create/complete/edit/delete VTODO items
|
|
18
|
+
- **Contacts** — list address books, list/get/export vCards
|
|
19
|
+
- **Login wizard** that validates the credentials with a `PROPFIND` and stores the password in the OS keyring (with a `chmod 0600` JSON fallback)
|
|
20
|
+
- **JSON output everywhere** so you can pipe into `jq` and friends
|
|
21
|
+
- `-h` / `--help` available on every command and subcommand
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install nextcloud-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or from source:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/AlexMili/nextcloud-cli
|
|
33
|
+
cd nextcloud-cli
|
|
34
|
+
pip install -e .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The installed binary is **`nxcloud`**.
|
|
38
|
+
|
|
39
|
+
## Login
|
|
40
|
+
|
|
41
|
+
Create a Nextcloud **app password** first
|
|
42
|
+
(`Settings → Security → App passwords`), then:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
nxcloud login
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
You'll only be prompted for what's missing. Values are resolved in this order:
|
|
49
|
+
|
|
50
|
+
1. CLI flag (`--url`, `--username`, `--password`, `--timezone`)
|
|
51
|
+
2. Environment variable (`NEXTCLOUD_URL`, `NEXTCLOUD_USER`, `NEXTCLOUD_TOKEN`, `NEXTCLOUD_TIMEZONE`)
|
|
52
|
+
3. Interactive prompt
|
|
53
|
+
|
|
54
|
+
So all of these work:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Fully interactive
|
|
58
|
+
nxcloud login
|
|
59
|
+
|
|
60
|
+
# Mixed: URL from env, prompt for the rest
|
|
61
|
+
NEXTCLOUD_URL=https://nc.example.com nxcloud login
|
|
62
|
+
|
|
63
|
+
# Fully non-interactive (no prompts)
|
|
64
|
+
nxcloud login \
|
|
65
|
+
--url https://nc.example.com \
|
|
66
|
+
--username alice \
|
|
67
|
+
--password 'app-pass-here' \
|
|
68
|
+
--timezone Europe/Paris
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
You can also skip persistence entirely and rely on environment variables for
|
|
72
|
+
every command:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
export NEXTCLOUD_URL=https://nc.example.com
|
|
76
|
+
export NEXTCLOUD_USER=alice
|
|
77
|
+
export NEXTCLOUD_TOKEN=app-pass-here
|
|
78
|
+
export NEXTCLOUD_TIMEZONE=Europe/Paris
|
|
79
|
+
nxcloud check
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To remove stored credentials:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
nxcloud logout
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Usage
|
|
89
|
+
|
|
90
|
+
Every command emits JSON on stdout for easy scripting. Use `-h` on any
|
|
91
|
+
command or subcommand for built-in help.
|
|
92
|
+
|
|
93
|
+
### Connectivity check
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
nxcloud check
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Files
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
nxcloud files list --path /Documents
|
|
103
|
+
nxcloud files upload --local ./report.pdf --remote /Documents/report.pdf
|
|
104
|
+
nxcloud files download --remote /Documents/report.pdf --local ./report.pdf
|
|
105
|
+
nxcloud files move --src /tmp/a.txt --dst /archive/a.txt
|
|
106
|
+
nxcloud files mkdir --path /new-folder
|
|
107
|
+
nxcloud files delete --path /old.txt
|
|
108
|
+
nxcloud files search --query report --limit 20 # OCS unified search (server-side)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Notes (requires the Nextcloud Notes app)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
nxcloud notes list
|
|
115
|
+
nxcloud notes list --category Work # notes in the "Work" folder
|
|
116
|
+
nxcloud notes list --category "Work/Projects" # nested folder (subdirectory)
|
|
117
|
+
nxcloud notes list --category="" # only notes at the Notes/ root (no category)
|
|
118
|
+
nxcloud notes list --limit 10 # cap the number of notes fetched
|
|
119
|
+
nxcloud notes get --id 941
|
|
120
|
+
nxcloud notes create --title "Meeting" --content "Q3 roadmap." --category Work
|
|
121
|
+
nxcloud notes edit --id 941 --title "Updated"
|
|
122
|
+
nxcloud notes delete --id 941
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> In the Nextcloud Notes app, **category = folder**: notes are stored as
|
|
126
|
+
> Markdown files under `Notes/<category>/`, and `/` separates subdirectories.
|
|
127
|
+
> `--category` matches **exactly** — `--category Work` does not include
|
|
128
|
+
> `Work/Projects`. Use `--category=""` to list only notes at the root.
|
|
129
|
+
|
|
130
|
+
### Calendar
|
|
131
|
+
|
|
132
|
+
List calendars and events:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
nxcloud calendar list
|
|
136
|
+
nxcloud calendar events --calendar Personal --start 2026-05-01 --end 2026-05-31
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Date-range shortcuts (server-side filtering, in your configured timezone):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
nxcloud calendar events --calendar Personal --today
|
|
143
|
+
nxcloud calendar events --calendar Personal --this-week # current Mon → Mon
|
|
144
|
+
nxcloud calendar events --calendar Personal --next-week # upcoming Mon → Mon
|
|
145
|
+
nxcloud calendar events --calendar Personal --this-month # 1st → 1st of next month
|
|
146
|
+
nxcloud calendar events --calendar Personal --next-month
|
|
147
|
+
nxcloud calendar events --calendar Personal --next 7d # also: 48h, 2w
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
> Shortcuts are mutually exclusive with each other and with `--start/--end`.
|
|
151
|
+
|
|
152
|
+
Create an event with attendees and an organizer:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
nxcloud calendar create \
|
|
156
|
+
--calendar Work \
|
|
157
|
+
--summary "Project sync" \
|
|
158
|
+
--start 2026-07-01T14:00:00 \
|
|
159
|
+
--end 2026-07-01T15:00:00 \
|
|
160
|
+
--location "Room 4B" \
|
|
161
|
+
--description "Quarterly review" \
|
|
162
|
+
--organizer "Alice <alice@example.com>" \
|
|
163
|
+
--attendee "Bob <bob@example.com>" \
|
|
164
|
+
--attendee carol@example.com
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`--attendee` is repeatable and accepts either a bare email or the
|
|
168
|
+
`Name <email>` form.
|
|
169
|
+
|
|
170
|
+
Edit an event (including adding/removing invitees):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
nxcloud calendar edit --calendar Work --uid <uid> --summary "New title"
|
|
174
|
+
nxcloud calendar edit --calendar Work --uid <uid> \
|
|
175
|
+
--add-attendee "Dan <dan@example.com>" \
|
|
176
|
+
--remove-attendee carol@example.com
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Delete an event:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
nxcloud calendar delete --calendar Work --uid <uid>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Search events server-side (CalDAV `text-match`). Combine with date filters:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
nxcloud calendar search --calendar Work --query standup
|
|
189
|
+
nxcloud calendar search --calendar Work --query roadmap --in description
|
|
190
|
+
nxcloud calendar search --calendar Work --query "1:1" --this-week
|
|
191
|
+
# --in: summary | description | location | category | all (default: summary)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Tasks (VTODO)
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
nxcloud tasks list
|
|
198
|
+
nxcloud tasks list --include-completed
|
|
199
|
+
nxcloud tasks create --summary "Review PR" --due 2026-07-05 --priority 1
|
|
200
|
+
nxcloud tasks complete --uid <uid>
|
|
201
|
+
nxcloud tasks edit --uid <uid> --summary "Updated summary"
|
|
202
|
+
nxcloud tasks delete --uid <uid>
|
|
203
|
+
nxcloud tasks search --query "deploy" --include-completed
|
|
204
|
+
nxcloud tasks search --query "fix" --in description --list Work
|
|
205
|
+
# --in: summary | description | category | all (default: summary)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Contacts
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
nxcloud contacts list
|
|
212
|
+
nxcloud contacts cards --addressbook contacts
|
|
213
|
+
nxcloud contacts get --addressbook contacts --uid <uid>
|
|
214
|
+
nxcloud contacts export --addressbook contacts --uid <uid> --local ./alice.vcf
|
|
215
|
+
nxcloud contacts search --addressbook contacts --query alex
|
|
216
|
+
nxcloud contacts search --addressbook contacts --query "@example.com" --in email
|
|
217
|
+
# --in: name | email | phone | all (default: all)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Configuration files
|
|
221
|
+
|
|
222
|
+
| File | Purpose | Permissions |
|
|
223
|
+
|------|---------|-------------|
|
|
224
|
+
| `~/.config/nextcloud-cli/config.json` | URL, username, timezone | `0600` |
|
|
225
|
+
| OS keyring (entry `nextcloud-cli`) | App password | OS-managed |
|
|
226
|
+
| `~/.config/nextcloud-cli/secrets.json` | Password fallback when no keyring backend is available | `0600` |
|
|
227
|
+
|
|
228
|
+
Override the config directory with the `NEXTCLOUD_CLI_HOME` environment variable.
|
|
229
|
+
|
|
230
|
+
## Help
|
|
231
|
+
|
|
232
|
+
`-h` and `--help` are wired up at every level:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
nxcloud --help
|
|
236
|
+
nxcloud calendar --help
|
|
237
|
+
nxcloud calendar create --help
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|