Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 155 additions & 123 deletions README.md
Original file line number Diff line number Diff line change
@@ -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 <id>
kscli documents create --name "My Doc" --parent-path-part-id <id>
kscli chunks search --query "semantic search" --folder-id <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 <your-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 <agent>` |
| **Recall by meaning, not keyword** | `kscli chunks search -q "$prompt" -p <agent> -l 5` |
| **Per-agent / per-project namespaces** | `kscli folders create --name "agent:openclaw:project-x"` |
| **Forget specific things** | `kscli documents delete <id>` |
| **Inspect what the agent knows** | `kscli folders list -p <agent> -f tree` |
| **Audit which memory shaped a reply** | `kscli chunk-lineages describe <chunk>` |

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 <your-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 <id>
kscli documents describe <doc-id>
kscli documents ingest --name "report.pdf" --file ./report.pdf --parent-path-part-id <id>
### Claude Code

# Search chunks
kscli chunks search --query "quarterly revenue" --folder-id <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 <name>` | 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 <group> --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).
2 changes: 2 additions & 0 deletions src/kscli/commands/agent_help.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Loading