Vikunja tooling for agent harnesses
Standard-library Python only, so any device can run it without a virtualenv: vk CLI -- for harnesses that can shell out vikunja_mcp.py MCP server (stdio) -- for harnesses that speak MCP vkclient.py shared client vk-watch@.service systemd template for the per-device task watcher AGENT-ONBOARDING.md is a prompt you can hand to an agent so it configures its own access and verifies it.
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
# Vikunja access — agent onboarding prompt
|
||||
|
||||
Hand the block below to any agent that needs Vikunja access. It is written to be
|
||||
pasted verbatim as a task prompt. Everything after the `---` is the prompt.
|
||||
|
||||
Before pasting, substitute:
|
||||
|
||||
- `<AGENT_NAME>` — the bot account for this harness, e.g. `bot-nullclaw`
|
||||
- `<HARNESS>` — `claude-code`, `omp`, `picocode`, or `other`
|
||||
|
||||
---
|
||||
|
||||
## Task: configure your own Vikunja access
|
||||
|
||||
You are `<AGENT_NAME>`. Give yourself working access to Vikunja at
|
||||
`https://todo.dominat.us`, then verify it and report what you can and cannot see.
|
||||
|
||||
### Facts you need
|
||||
|
||||
- Tooling lives at `/srv/pods/vikunja-agents/` on `reptar`: `vk` (CLI),
|
||||
`vkclient.py` (shared client), `vikunja_mcp.py` (MCP server, stdio).
|
||||
Standard-library Python only — no virtualenv, no pip install.
|
||||
- If you are **not** on `reptar`, copy those three files to the machine you run
|
||||
on (`~/opt/vikunja-agents/`) and symlink `vk` onto your `PATH`.
|
||||
- Auth is a Vikunja **API token**, read from `~/.config/vikunja-agents/config.json`
|
||||
(mode 0600) or `$VIKUNJA_TOKEN`. Select an identity with `$VIKUNJA_PROFILE`.
|
||||
- Your account must already exist. The normal shape is a **bot user**: a local
|
||||
account owned by a human, with no password of its own. If it does not exist,
|
||||
stop and ask — creating one is your owner's job (Vikunja UI: Settings → Bot
|
||||
Users). MAS/OIDC accounts cannot be used for this (see constraints).
|
||||
|
||||
### Step 1 — get your token (once)
|
||||
|
||||
**If your account is a bot user** (the normal case — it has an owner and no
|
||||
password), you cannot mint your own token: token creation needs a password login
|
||||
and bots have none. Your owner mints it for you, then hands it over out of band.
|
||||
Store it without putting it in argv or shell history:
|
||||
|
||||
```sh
|
||||
vk profile <AGENT_NAME> --username <AGENT_NAME> < /path/to/token-file
|
||||
# or: pbpaste | vk profile <AGENT_NAME> --username <AGENT_NAME>
|
||||
```
|
||||
|
||||
`vk profile` verifies the token against the API before saving, so a bad paste
|
||||
fails loudly instead of silently writing a dead profile. It lands in
|
||||
`~/.config/vikunja-agents/config.json` at mode 0600.
|
||||
|
||||
If you have no token, stop and ask your owner for one. They create it from
|
||||
Vikunja's UI (Settings → API tokens, issued for your bot) or with an
|
||||
authenticated `PUT /api/v1/tokens` carrying `owner_id: <your user id>`.
|
||||
|
||||
**If your account is instead a plain user with a password** (legacy), you can
|
||||
mint your own:
|
||||
|
||||
```sh
|
||||
VIKUNJA_PASSWORD="$(cat ~/.config/vikunja-agents/<AGENT_NAME>.password)" \
|
||||
vk bootstrap --username <AGENT_NAME> --title "<HARNESS> ($(hostname))"
|
||||
```
|
||||
|
||||
Either way: **never echo the token, paste it into a chat, or commit it.** It
|
||||
expires in a year and cannot renew itself — renewal means asking your owner
|
||||
again.
|
||||
|
||||
### Step 2 — register the MCP server for your harness
|
||||
|
||||
`claude-code`:
|
||||
|
||||
```sh
|
||||
claude mcp add vikunja -e VIKUNJA_PROFILE=<AGENT_NAME> -- /srv/pods/vikunja-agents/vikunja_mcp.py
|
||||
```
|
||||
|
||||
`omp` — add to `~/.omp/agent/mcp.json` (create it if absent):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"vikunja": {
|
||||
"type": "stdio",
|
||||
"command": "/srv/pods/vikunja-agents/vikunja_mcp.py",
|
||||
"env": { "VIKUNJA_PROFILE": "<AGENT_NAME>" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`picocode` — add to `picocode.yaml`:
|
||||
|
||||
```yaml
|
||||
mcp:
|
||||
vikunja:
|
||||
command: /srv/pods/vikunja-agents/vikunja_mcp.py
|
||||
env:
|
||||
VIKUNJA_PROFILE: <AGENT_NAME>
|
||||
auto_allow:
|
||||
- "^vikunja_list_"
|
||||
- "^vikunja_get_"
|
||||
```
|
||||
|
||||
`other` — the server speaks MCP over stdio (JSON-RPC 2.0, newline-delimited).
|
||||
Run `/srv/pods/vikunja-agents/vikunja_mcp.py` with `VIKUNJA_PROFILE` set. If your
|
||||
harness cannot speak MCP, skip this step and use the `vk` CLI instead; it covers
|
||||
the same ground.
|
||||
|
||||
### Step 3 — verify, and do not skip this
|
||||
|
||||
```sh
|
||||
vk whoami # must print <AGENT_NAME>
|
||||
vk projects # the projects you can actually see
|
||||
vk tasks --mine # your queue
|
||||
```
|
||||
|
||||
Then confirm the MCP path independently of the CLI — restart your harness if it
|
||||
binds MCP servers at startup (claude-code does), and call `vikunja_list_projects`.
|
||||
If the tool is missing, the registration did not take; if it errors, the token
|
||||
did not take. These are different failures — do not report one as the other.
|
||||
|
||||
### Step 4 — report
|
||||
|
||||
State plainly:
|
||||
|
||||
1. Which projects you can see (likely only your own `Inbox` — see constraints).
|
||||
2. Whether MCP tools are available, or whether you fell back to the CLI.
|
||||
3. Anything you had to ask a human for.
|
||||
|
||||
### Constraints that will otherwise cost you an hour
|
||||
|
||||
- **A token cannot mint another token.** Vikunja excludes the `tokens` route
|
||||
group from anything an API token can be granted. For a bot user that means
|
||||
only your owner can issue or renew your token; you can never do it yourself,
|
||||
and there is no password you could use even if you wanted to.
|
||||
- **You cannot ask the API who you are.** `/user` is unreachable with a token
|
||||
(`user_*` routes are excluded too). `vk whoami` reads the username from your
|
||||
config file. Do not try to fix a 401 on `/user` — it is expected.
|
||||
- **You start with only your own Inbox.** A new account sees nothing else until a
|
||||
human shares projects with it. If `vk projects` shows one project, that is
|
||||
normal, not a broken token — say so and ask for the shares you need.
|
||||
- **Assignment is dispatch.** Work reaches you by being assigned to
|
||||
`<AGENT_NAME>`. Use `vk tasks --mine`. Do not scrape other agents' queues.
|
||||
- **Username lookup is project-scoped.** Resolving a username to an id uses
|
||||
`/projects/{id}/projectusers`; the instance-wide `/users` search is not
|
||||
grantable to tokens. You can only assign to users who can access that project.
|
||||
- **Updates replace the whole task.** The client merges for you; if you call the
|
||||
API directly, read-modify-write or you will blank fields.
|
||||
- **Link your work back.** Put `VK-<task id>` in commit messages, and
|
||||
`fixes VK-<id>` to close a task on push — a Gitea bridge posts the commit link
|
||||
onto the task. Without it a task says "done" but never says what changed.
|
||||
|
||||
### Rules
|
||||
|
||||
- One account per harness. Do not share a profile with another agent — separate
|
||||
accounts are what make the task history say who did what.
|
||||
- Never print, log, or transmit the token or password. If you think one leaked,
|
||||
say so immediately; rotation needs a human.
|
||||
- Comment on tasks when you finish work, find something that changes scope, or
|
||||
are blocked. Do not narrate routine steps.
|
||||
Reference in New Issue
Block a user