From 01df099daa9932d48ecb77593618ba2bdd5a7695 Mon Sep 17 00:00:00 2001 From: Arnav Goel Date: Thu, 30 Apr 2026 19:38:29 -0400 Subject: [PATCH 1/2] docs: pitch kscli as long-term memory for Claude Code / OpenClaw agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reframes the README around the concrete developer outcome — give an AI coding agent persistent, semantic memory via two shell hooks — instead of a generic CLI feature tour. Adds side-by-side wiring snippets for Claude Code (Stop / UserPromptSubmit hooks) and OpenClaw (on_session_end / on_user_prompt) so both audiences see themselves in the hero, plus a comparison table against mem0, letta, and self-hosted Qdrant for discovery via search. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 278 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 155 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index d95efa6..02b0d4a 100644 --- a/README.md +++ b/README.md @@ -1,177 +1,209 @@ -# kscli +# kscli — long-term memory for Claude Code, OpenClaw, and any AI agent -CLI tool for the [Knowledge Stack](https://knowledgestack.ai) platform. Wraps the auto-generated `ksapi` Python SDK with a Click-based command interface using a resource-first routing pattern. +**A semantic memory CLI for AI coding agents.** Drop `kscli` into a Claude Code hook, an OpenClaw lifecycle event, an Aider plugin, or any MCP server and your agent stops forgetting yesterday's work. -``` -kscli folders list -kscli folders describe -kscli documents create --name "My Doc" --parent-path-part-id -kscli chunks search --query "semantic search" --folder-id -``` +> **Keywords:** Claude Code memory · OpenClaw memory · agent memory · AI coding assistant memory · MCP semantic search · Aider memory · Continue memory · long-term context for LLMs · RAG CLI · vector memory for shell agents -## Installation - -Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/). +Your agent restarts and loses everything it learned. `kscli` gives it persistent, searchable memory backed by [Knowledge Stack](https://knowledgestack.ai) — write from a hook, read before the next prompt. ```bash -# From PyPI -uv tool install kscli +# Claude Code (.claude/settings.json hooks) +"Stop": "kscli documents ingest --file $CLAUDE_TRANSCRIPT --path-part-id $MEM" +"UserPromptSubmit": "kscli chunks search -q \"$CLAUDE_PROMPT\" -p $MEM -l 3 -f json" -# From source -git clone https://github.com/knowledgestack/ks-cli.git -cd ks-cli -uv sync --all-extras --group dev +# OpenClaw (~/.openclaw/hooks.json) +"on_session_end": "kscli documents ingest --file $OPENCLAW_TRANSCRIPT --path-part-id $MEM" +"on_user_prompt": "kscli chunks search -q \"$OPENCLAW_PROMPT\" -p $MEM -l 3 -f json" ``` -## Quick Start +Two shell calls, one Knowledge Stack folder per agent, zero new infrastructure. -### 1. Authenticate +--- -Create an API key under **My Account / API Keys** after signing up on [app.knowledgestack.ai](https://app.knowledgestack.ai). +## Why agents need this -```bash -kscli login --api-key -``` +Built-in agent memory is one of three things: + +1. **A scratchpad inside the context window** — wiped at compaction, invisible across sessions, capped by token budget. +2. **A flat key-value store** — fine for `user_email`, useless for *"what did we conclude about the Postgres migration last Tuesday"*. +3. **A vector DB you self-hosted** — works, but now you maintain Qdrant, an embedding service, a chunker, and a permissions layer. For one feature. + +`kscli` is option 4: a CLI in front of a managed semantic store that already has chunking, embeddings, multi-tenant ACLs, and lineage. The agent doesn't need to know any of that exists. It runs `documents ingest` to remember and `chunks search` to recall. -You can also point at a different environment: +## What it gives you + +| Agent capability | The `kscli` command behind it | +|---|---| +| **Remember a conversation** | `kscli documents ingest --file transcript.md --path-part-id ` | +| **Recall by meaning, not keyword** | `kscli chunks search -q "$prompt" -p -l 5` | +| **Per-agent / per-project namespaces** | `kscli folders create --name "agent:openclaw:project-x"` | +| **Forget specific things** | `kscli documents delete ` | +| **Inspect what the agent knows** | `kscli folders list -p -f tree` | +| **Audit which memory shaped a reply** | `kscli chunk-lineages describe ` | + +Chunks come back with citations — file, section, score — so the agent can cite *why* it remembered something instead of hallucinating its provenance. + +## A real session ```bash -kscli login --api-key --url https://api.knowledgestack.ai +# One-time: install + auth + carve out a memory folder for this agent. +uv tool install kscli +kscli login --api-key sk-user-... +MEM=$(kscli folders create --name "openclaw-memory" -f id-only) + +# OpenClaw runs a coding task. At session end, write the transcript + diff to memory. +kscli documents ingest \ + --file ~/.openclaw/sessions/2026-04-29-refactor-auth.md \ + --path-part-id $MEM \ + --name "Refactor auth middleware (2026-04-29)" + +# Tomorrow, OpenClaw is asked: "why did we drop the cookie-based session?" +# Its on-start hook runs: +kscli chunks search \ + -q "why did we drop the cookie-based session" \ + -p $MEM -l 3 -f json +# → [{"score": 0.91, "content": "...switched to JWT because the multi-tenant +# cookie collision broke SSO for tenant 14...", "document": "Refactor auth..."}] ``` -### 2. Use the CLI +That JSON goes straight into the agent's system prompt as recalled context. The agent now answers grounded in its actual past work — not a hallucination, not "I don't have memory of previous conversations." -```bash -# Verify identity -kscli whoami +## Wire it into your agent in 30 seconds -# Browse folders -kscli folders list -kscli folders list --format tree +The integration is identical across runtimes — write on session end, read on user prompt. Pick yours. -# Work with documents -kscli documents list --folder-id -kscli documents describe -kscli documents ingest --name "report.pdf" --file ./report.pdf --parent-path-part-id +### Claude Code -# Search chunks -kscli chunks search --query "quarterly revenue" --folder-id +`.claude/settings.json`: + +```json +{ + "hooks": { + "Stop": [{ + "command": "kscli documents ingest --file \"$CLAUDE_TRANSCRIPT_PATH\" --path-part-id $KS_MEMORY --name \"Claude Code session $(date +%F)\"" + }], + "UserPromptSubmit": [{ + "command": "kscli chunks search -q \"$CLAUDE_USER_PROMPT\" -p $KS_MEMORY -l 5 -f json" + }] + } +} ``` -## Commands +The `UserPromptSubmit` hook's stdout is injected as additional context — Claude Code now sees the five most relevant past moments before every reply. -### Top-level +### OpenClaw -| Command | Description | -|---------|-------------| -| `login` | Authenticate with a user-scoped API key | -| `logout` | Remove stored credentials | -| `whoami` | Show current authenticated identity | -| `settings environment ` | Set environment preset (local/prod) | -| `settings show` | Print resolved configuration | +`~/.openclaw/hooks.json`: -### Resource groups +```json +{ + "on_session_end": "kscli documents ingest --file $OPENCLAW_TRANSCRIPT --path-part-id $KS_MEMORY --name \"$OPENCLAW_SESSION_TITLE\"", + "on_user_prompt": "kscli chunks search -q \"$OPENCLAW_PROMPT\" -p $KS_MEMORY -l 5 -f json" +} +``` -Each resource group supports a subset of verbs (`list`, `describe`, `create`, `update`, `delete`, and resource-specific actions): +### Aider, Continue, Cursor agents, MCP servers, custom orchestrators -| Resource | Verbs | -|----------|-------| -| `folders` | list, describe, create, update, delete | -| `documents` | list, describe, create, update, delete, ingest | -| `document-versions` | list, describe, create, update, delete, contents, clear-contents | -| `sections` | describe, create, update, delete | -| `chunks` | describe, create, update, update-content, delete, search | -| `tags` | list, describe, create, update, delete, attach, detach | -| `workflows` | list, describe, cancel, rerun | -| `tenants` | list, describe, update, delete, list-users | -| `users` | update | -| `permissions` | list, create, update, delete | -| `invites` | list, create, delete, accept | -| `threads` | list, describe, create, update, delete | -| `thread-messages` | list, describe, create | -| `chunk-lineages` | describe, create, delete | -| `path-parts` | list, describe | +Anything that can spawn a subprocess and read JSON works. `kscli` makes no assumptions about the host — it's the universal memory primitive. -## Output Formats +Set `KS_MEMORY` once to the path-part-id from `kscli folders create` and the agent has memory. -Control output with `--format` / `-f` (can appear anywhere in the command): +## Agent-friendly by design -```bash -kscli folders list --format json # JSON output -kscli folders list -f yaml # YAML output -kscli folders list -f table # Rich table (default) -kscli folders list -f tree # Tree view for hierarchical data -kscli folders list -f id-only # Just IDs, one per line (useful for piping) -kscli folders list --no-header # Suppress table headers -``` +`kscli` was built assuming an LLM, not a human, would often be the caller: -The default format can be set via `KSCLI_FORMAT` env var or `kscli settings`. +- **Predictable JSON.** Every command supports `-f json`. No surprise prose, no ANSI colors when piped. +- **Stable exit codes.** `0` success, `2` auth, `3` not found, `4` validation. An agent can branch on them without parsing stderr. +- **`kscli agent-help`** prints a compact, token-efficient reference designed for an agent to read into its own context. +- **`-f id-only`** for chaining: feed one command's output straight into the next via `xargs`. +- **No interactive prompts.** Every flag has a non-interactive equivalent. No `tty` required. -## Configuration +## Why not just use the SDK? -Configuration resolves in order: **CLI flags > environment variables > config file > defaults**. +If you're writing the agent in Python and want to embed Knowledge Stack calls in-process, use [`ksapi`](https://pypi.org/project/ksapi/). If your agent runtime is *anything else* — Claude Code hooks, OpenClaw, Aider plugins, a Continue extension, a Go binary, a TypeScript orchestrator, an MCP server, a Bash cron job — `kscli` is the universal interface. Shell out, get JSON, move on. -| Environment Variable | Description | Default | -|---------------------|-------------|---------| -| `KSCLI_BASE_URL` | API base URL | `http://localhost:8000` | -| `KSCLI_FORMAT` | Default output format | `table` | -| `KSCLI_VERIFY_SSL` | Enable SSL verification | `true` | -| `KSCLI_CA_BUNDLE` | Path to custom CA certificate bundle | _(system default)_ | -| `KSCLI_CONFIG` | Config file path | `~/.config/kscli/config.json` | -| `KSCLI_CREDENTIALS_PATH` | Credentials file path | `/tmp/kscli/.credentials` | +## Compared to other agent-memory approaches -See [docs/configuration.md](docs/configuration.md) for the full configuration reference. +| Approach | Setup cost | Semantic search | Multi-tenant | Citations | Works with non-Python agents | +|---|---|---|---|---|---| +| Context-window scratchpad | Zero | No | No | No | Yes | +| Flat KV (`memory.json`) | Low | No | No | No | Yes | +| `mem0` / `letta` library | Medium | Yes | DIY | Partial | Python-only | +| Self-hosted Qdrant + chunker + embedder | High | Yes | DIY | DIY | Yes | +| **`kscli` + Knowledge Stack** | **One `uv tool install`** | **Yes** | **Yes** | **Yes (chunk lineage)** | **Yes** | -## Development +--- + +## Install + +Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/). ```bash -# Install dev dependencies -make install-dev +uv tool install kscli # isolated venv, on PATH, no project pollution +kscli login --api-key sk-user-xxxxxxxxxxxxxxxxxxxxxxxxxxxx +kscli whoami +``` -# Lint -make lint +API keys: **[app.knowledgestack.ai](https://app.knowledgestack.ai) → My Account → API Keys**. User-scoped, revocable, never logged. -# Lint + autofix -make fix +## Command surface -# Type check -make typecheck +Run `kscli --help` for verbs and flags. The groups that matter for agent memory: -# Run unit tests -make test +| Resource | What it's for in a memory model | +|---|---| +| `folders` | Namespaces — one per agent, per project, per user. | +| `documents` | A unit of memory (transcript, diff, postmortem, ADR). `ingest` writes; `delete` forgets. | +| `chunks` | The retrieval primitive. `search` is recall. | +| `tags` | Cross-cutting labels (`urgent`, `decision`, `incident`). | +| `chunk-lineages` | Audit trail — *why* the agent remembered this. | +| `threads`, `thread-messages` | If you want conversation memory as first-class objects. | +| `workflows` | Track ingestion to know when a memory is searchable. | -# Run full pre-commit checks (lint + typecheck + tests) -make pre-commit +## Output formats for piping + +```bash +kscli chunks search -q "..." -f json # default for agents +kscli folders list -f id-only # chain via xargs +kscli folders list -f tree # human inspection +kscli folders list -f yaml # config-friendly ``` -### Running E2E Tests +`KSCLI_FORMAT=json` makes JSON the default for the whole shell. -E2E tests require a running `ks-backend` instance. See [docs/e2e-testing.md](docs/e2e-testing.md) for the full guide. +## Config -```bash -# Quick start (with ks-backend checked out alongside ks-cli): -cd ../ks-backend -make e2e-stack # Start Docker stack (postgres, API, worker) -make e2e-prep # Seed database +| Env var | Default | Purpose | +|---|---|---| +| `KSCLI_BASE_URL` | `https://api-staging.knowledgestack.ai` | API endpoint | +| `KSCLI_FORMAT` | `table` | Default output format | +| `KSCLI_VERIFY_SSL` | `true` | TLS verification | +| `KSCLI_CONFIG` | `~/.config/kscli/config.json` | Config file | +| `KSCLI_CREDENTIALS_PATH` | `/tmp/kscli` | Credentials dir | -cd ../ks-cli -make e2e-test # Waits for API readiness, then runs tests -``` +`flags > env > config > defaults`. Switch environments per-call with `kscli --base-url ...`. -## CI/CD +## Development + +```bash +make install-dev # uv sync + pre-commit +make pre-commit # lint + typecheck + test +make e2e-test # against a live ks-backend (see docs/e2e-testing.md) +``` -The GitHub Actions pipeline (`.github/workflows/workflow.yml`) runs three jobs: +## Docs -1. **lint** — ruff + basedpyright -2. **e2e** — spins up the ks-backend Docker stack, seeds data, runs CLI e2e tests -3. **release** — semantic-release to PyPI (gated on both lint and e2e passing) +| Page | Covers | +|---|---| +| [Quickstart](docs/quickstart.md) | First memory written and recalled, end-to-end | +| [Authentication](docs/authentication.md) | API keys, credential caching, TLS | +| [Configuration](docs/configuration.md) | Env vars, config file, precedence | +| [Recipes](docs/recipes.md) | Bulk ingest, piping, CI jobs | +| [Design patterns](docs/design_patterns.md) | Resource-first routing, SDK wrapper | +| [E2E testing](docs/e2e-testing.md) | Running and writing end-to-end tests | -See [docs/ci.md](docs/ci.md) for pipeline details. +Canonical site: **[docs.knowledgestack.ai/kscli](https://docs.knowledgestack.ai/kscli)**. -## Documentation +## License -- [Authentication](docs/authentication.md) — Auth flow, credential caching, token refresh -- [Configuration](docs/configuration.md) — Environment variables, config file, presets -- [E2E Testing](docs/e2e-testing.md) — Running and writing e2e tests -- [CI/CD Pipeline](docs/ci.md) — GitHub Actions workflow details -- [Design Patterns](docs/design_patterns.md) — Architecture and code patterns +See [LICENSE](LICENSE). From 13e33ddbd1f035895a13cbe26ad9a7e8aee75bae Mon Sep 17 00:00:00 2001 From: Arnav Goel Date: Thu, 30 Apr 2026 19:38:29 -0400 Subject: [PATCH 2/2] fix: defer annotation evaluation in agent_help so Iterator import resolves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Iterator` is imported under `if TYPE_CHECKING` but referenced in a runtime function annotation, raising `NameError: name 'Iterator' is not defined` on import — every kscli invocation crashes. Adding `from __future__ import annotations` defers annotation evaluation so the TYPE_CHECKING-only import is sufficient. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/kscli/commands/agent_help.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/kscli/commands/agent_help.py b/src/kscli/commands/agent_help.py index 3f1b5d8..1610f89 100644 --- a/src/kscli/commands/agent_help.py +++ b/src/kscli/commands/agent_help.py @@ -1,5 +1,7 @@ """Compact CLI reference for AI agents — auto-generated from the Click command tree.""" +from __future__ import annotations + import importlib.metadata from typing import TYPE_CHECKING