[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CS613RWD9CFJ3KFX47V1DS":3,"skill-same:01M6CS613RWD9CFJ3KFX47V1DS":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":50,"ownerDescription":51,"updatedAt":52,"install":53,"resources":66},"01M6CS613RWD9CFJ3KFX47V1DS","system-management",null,"Use when reading or changing GHOST configuration (providers, models, timing, compaction, services, any config.toml key), adding or switching LLM providers, answering questions about GHOST's own features or capabilities, a CLI tool is missing or \"not found\", services need starting\u002Fstopping\u002Fdebugging, updating GHOST to a newer version, managing the Nix shell environment, or troubleshooting GHOST setup.","mrtolkien\u002FGHOST","mrtolkien","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F8489650?v=4","01M6CS32Q934XBQQE8BDV5Z6W2","Tolki","01M6CS32VBCD47F5E27WF9W6FC",5,"MIT","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsystem-management\u002Fskill.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"system","system management","management","tool","nix","configuration","models","version","use","environment","config","troubleshooting","setup","cli","ghost","shell","Providers","services","capabilities","debugging","2026-11-10 10:12:30",false,"---\nname: system-management\ndescription:\n  Use when reading or changing GHOST configuration (providers, models, timing,\n  compaction, services, any config.toml key), adding or switching LLM providers,\n  answering questions about GHOST's own features or capabilities, a CLI tool is missing\n  or \"not found\", services need starting\u002Fstopping\u002Fdebugging, updating GHOST to a newer\n  version, managing the Nix shell environment, or troubleshooting GHOST setup.\n---\n\n# System Management\n\nManage GHOST's configuration, providers, embedded documentation, shell environment,\nservices, and self-update mechanism.\n\n## Self-Documentation\n\nGHOST bundles its own documentation into the binary. On every daemon boot these docs are\nextracted to `$WORKSPACE\u002Freferences\u002Fghost\u002Fdocs\u002F` and indexed as references under the\ntopic `ghost\u002Fdocs`.\n\n**When the OPERATOR asks how a GHOST feature works, always search the embedded docs\nbefore answering.** Use the `knowledge_search` tool:\n\n```\nknowledge_search(query=\"\u003Cwhat the OPERATOR asked about>\", topic=\"ghost\", categories=[\"references\"])\n```\n\nTopic prefix matching means `topic=\"ghost\"` finds everything under `ghost\u002Fdocs` too. Use\na specific query — `\"compaction threshold\"` not `\"compaction\"`.\n\nIf `knowledge_search` returns nothing useful, read the file directly:\n\n    $WORKSPACE\u002Freferences\u002Fghost\u002Fdocs\u002F\n\nKey doc paths for common questions:\n\n| Topic              | Doc path (under `references\u002Fghost\u002Fdocs\u002F`) |\n| ------------------ | ----------------------------------------- |\n| Config options     | `getting-started\u002Fconfiguration.md`        |\n| Providers & models | `ghost\u002Fproviders.md`                      |\n| Workspace layout   | `getting-started\u002Fworkspace.md`            |\n| Services setup     | `getting-started\u002Fservices.md`             |\n| Knowledge system   | `knowledge\u002F`                              |\n| Agents & cron      | `agents\u002F`                                 |\n| Skills             | `skills-and-tools\u002F`                       |\n| Sessions & chat    | `chat\u002F`                                   |\n| CLI reference      | `reference\u002Fcli.md`                        |\n\n| Rationalization                  | Reality                                                                                  |\n| -------------------------------- | ---------------------------------------------------------------------------------------- |\n| \"I know how this feature works\"  | Training data may be stale. The embedded docs reflect the running version. Search first. |\n| \"I'll just read the source code\" | Docs are faster and written for explanation. Read source only if docs don't answer it.   |\n\n## Configuration\n\n### File Locations\n\n- **Settings**: `~\u002F.config\u002Fghost\u002Fconfig.toml` (override: `GHOST_CONFIG_DIR` env var)\n- **Secrets**: `~\u002F.config\u002Fghost\u002F.env` — API keys, bot tokens. Never put secrets in\n  config.toml.\n\n### Reading & Writing Config\n\n```\nghost config get \u003Ckey>              # read a value (defaults applied)\nghost config set \u003Ckey> \u003Cvalue>      # write a value (validates before saving)\nghost config reload                 # signal daemon to pick up changes (SIGHUP)\n```\n\nKeys use **dot-notation** for nested values:\n\n```\nghost config get models.primary.model\nghost config set models.primary.model \"anthropic\u002Fclaude-sonnet-4\"\nghost config set compaction.threshold 0.85\nghost config set web.search_max_results 10\nghost config reload\n```\n\nThe `set` command parses TOML syntax — numbers, booleans, strings, and inline tables all\nwork. Model aliases require both `provider` and `model` keys.\n\n### Decision: How to Change Config\n\n```dot\ndigraph config_decision {\n    \"OPERATOR wants a change\" [shape=diamond];\n    \"Single setting?\" [shape=diamond];\n    \"New provider or full reconfigure?\" [shape=diamond];\n    \"Secret (API key, token)?\" [shape=diamond];\n\n    \"ghost config set + reload\" [shape=box];\n    \"ghost init (re-run wizard)\" [shape=box];\n    \"Edit ~\u002F.config\u002Fghost\u002F.env\" [shape=box];\n\n    \"OPERATOR wants a change\" -> \"Secret (API key, token)?\";\n    \"Secret (API key, token)?\" -> \"Edit ~\u002F.config\u002Fghost\u002F.env\" [label=\"yes\"];\n    \"Secret (API key, token)?\" -> \"Single setting?\" [label=\"no\"];\n    \"Single setting?\" -> \"ghost config set + reload\" [label=\"yes\"];\n    \"Single setting?\" -> \"New provider or full reconfigure?\" [label=\"multiple\"];\n    \"New provider or full reconfigure?\" -> \"ghost init (re-run wizard)\" [label=\"yes\"];\n    \"New provider or full reconfigure?\" -> \"ghost config set + reload\" [label=\"just a few keys\"];\n}\n```\n\n### Hot-Reload vs Restart\n\nMost settings take effect after `ghost config reload`. A few require a full daemon\nrestart (`ghost reboot`):\n\n| Requires restart                                    | Hot-reloadable                                |\n| --------------------------------------------------- | --------------------------------------------- |\n| `workspace` (directory path)                        | `models.*.model`, `models.*.context_window`   |\n| `embeddings.dimension` (invalidates stored vectors) | `timing.*` (idle, scheduler tick)             |\n| `discord.enabled` (interface toggle)                | `compaction.*` (threshold, limits)            |\n|                                                     | `web.*` (search provider, results, crawl URL) |\n|                                                     | `docling.*` (URL, timeout)                    |\n|                                                     | `coding.model`                                |\n|                                                     | `debug.*` (request saving)                    |\n|                                                     | `discord.allowed_user_id`                     |\n|                                                     | `embeddings.url`, `embeddings.model`          |\n\n### Key Config Reference\n\nFor the full reference, search the embedded docs:\n\n```\nknowledge_search(query=\"config.toml reference\", topic=\"ghost\", categories=[\"references\"])\n```\n\nQuick reference for common keys:\n\n| Key                              | Example value                            | What it controls                        |\n| -------------------------------- | ---------------------------------------- | --------------------------------------- |\n| `models.default`                 | `\"primary\"` or `[\"primary\", \"fallback\"]` | Default model alias (or fallback chain) |\n| `models.\u003Calias>.provider`        | `\"openrouter\"`                           | Provider backend for this alias         |\n| `models.\u003Calias>.model`           | `\"anthropic\u002Fclaude-sonnet-4\"`            | Model ID at the provider                |\n| `models.\u003Calias>.context_window`  | `200000`                                 | Token limit for this model              |\n| `models.vision`                  | `\"fast\"`                                 | Model alias used for vision\u002FPDF tasks   |\n| `discord.allowed_user_id`        | `\"123456789\"`                            | OPERATOR's Discord user ID              |\n| `embeddings.url`                 | `\"http:\u002F\u002F127.0.0.1:11434\"`               | Embedding endpoint (Ollama)             |\n| `embeddings.model`               | `\"qwen3-embedding:8b\"`                   | Embedding model name                    |\n| `timing.reflection_idle_minutes` | `10`                                     | Minutes idle before reflection          |\n| `compaction.threshold`           | `0.90`                                   | Compact at this % of context window     |\n| `web.search.provider`            | `\"brave\"` or `\"searxng\"`                 | Web search backend                      |\n| `debug.save_requests`            | `false`                                  | Save raw LLM request\u002Fresponse dumps     |\n\n| Rationalization                             | Reality                                                                         |\n| ------------------------------------------- | ------------------------------------------------------------------------------- |\n| \"I'll just edit config.toml directly\"       | Use `ghost config set` — it validates before writing and catches syntax errors. |\n| \"I need to restart for this to take effect\" | Most settings are hot-reloadable. Check the table above.                        |\n| \"I don't know what config keys exist\"       | Search embedded docs: `knowledge_search(query=\"configuration\", topic=\"ghost\")`  |\n\n## Provider Management\n\n### Supported Providers\n\n| Provider     | Config value   | Auth              | Env var              |\n| ------------ | -------------- | ----------------- | -------------------- |\n| OpenRouter   | `openrouter`   | API key           | `OPENROUTER_API_KEY` |\n| Kimi Code    | `kimi_code`    | API key           | `KIMI_API_KEY`       |\n| Anthropic    | `anthropic`    | Claude Code OAuth | —                    |\n| OpenAI OAuth | `openai_oauth` | Device code flow  | —                    |\n\nUse the config values from this table exactly — they match the `ProviderKind` enum.\n\n### Common Operations\n\n**View current provider:**\n\n    ghost config get models.primary\n\n**Switch model (same provider):**\n\n    ghost config set models.primary.model \"new-model-id\"\n    ghost config reload\n\n**Add a new provider** — re-run the setup wizard. It validates credentials with a real\nAPI call before saving:\n\n    ghost init --provider openrouter --api-key sk-... --model anthropic\u002Fclaude-sonnet-4 --context-window 200000\n\nPass `--start` to restart services after. If run without flags, `ghost init` enters\ninteractive mode and prompts for each value.\n\n**Change an API key:**\n\nEdit `~\u002F.config\u002Fghost\u002F.env` directly, then:\n\n    ghost config reload\n\n**Validate setup:**\n\n    ghost status\n\nThis checks config validity and probes every configured service endpoint.\n\n### Decision: When to Use `ghost init` vs `ghost config set`\n\n```dot\ndigraph provider_decision {\n    \"Provider change\" [shape=diamond];\n    \"Same provider, different model?\" [shape=diamond];\n    \"New provider entirely?\" [shape=diamond];\n\n    \"ghost config set + reload\" [shape=box];\n    \"ghost init\" [shape=box];\n\n    \"Provider change\" -> \"Same provider, different model?\";\n    \"Same provider, different model?\" -> \"ghost config set + reload\" [label=\"yes\"];\n    \"Same provider, different model?\" -> \"New provider entirely?\" [label=\"no\"];\n    \"New provider entirely?\" -> \"ghost init\" [label=\"yes — validates credentials\"];\n}\n```\n\nUse `ghost init` for new providers because it tests the connection before saving. For\nsimple model swaps on an existing provider, `ghost config set` + `reload` is faster.\n\n| Rationalization                            | Reality                                                                                                     |\n| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |\n| \"I'll guess the provider name\"             | Use the exact `ProviderKind` values from the table: `openrouter`, `kimi_code`, `openai_oauth`, `anthropic`. |\n| \"I can set the API key in config.toml\"     | API keys go in `.env`, never in config.toml. Config is not secret.                                          |\n| \"I'll skip validation, it's probably fine\" | `ghost init` validates with a real API call. Use it for new providers. `ghost status` for existing ones.    |\n\n## Services\n\nGHOST's infrastructure has two tiers: **native services** (ghost-daemon, llama-server,\ndocling-serve) managed by the OS process supervisor, and **container services**\n(searxng, crawl4ai, chrome) managed by Podman\u002FDocker Compose.\n\nPrefer `ghost` CLI commands over raw systemctl\u002Flaunchctl\u002Fcompose:\n\n```\nghost start                   # start all services and the daemon\nghost stop                    # stop the daemon and all services\n\nghost services list           # show registered services and their state\nghost services add            # register a new service (interactive)\nghost services remove \u003Cname>  # unregister a service\nghost services update         # pull updates and restart all services\nghost services status         # check process-level status\n\nghost status                  # config validity + HTTP health probes\n```\n\nTo reconfigure ports, credentials, or which services are enabled: `ghost init`.\n\nFor health check endpoints, troubleshooting, and log commands, consult\n**`references\u002Fservices.md`**.\n\n## Shell Environment\n\n### Default: Install Permanently\n\nWhen a tool is needed, decide based on expected reuse:\n\n- **Recurring tool** (build tool, linter, language runtime, CLI used across sessions) --\n  add to the flake permanently.\n- **Rare\u002Fone-off binary** (single-use converter, one-time migration tool) -- use\n  `nix shell` for a temporary run.\n\nWhen unsure, install permanently. Removing a package later is trivial; losing time to a\nmissing tool in the next session is not.\n\n```dot\ndigraph shell_decision {\n    \"Need a CLI tool\" [shape=diamond];\n    \"Recurring or likely reused?\" [shape=diamond];\n    \"Add to flake\" [shape=box];\n    \"nix shell one-off\" [shape=box];\n\n    \"Need a CLI tool\" -> \"Recurring or likely reused?\";\n    \"Recurring or likely reused?\" -> \"Add to flake\" [label=\"yes or unsure\"];\n    \"Recurring or likely reused?\" -> \"nix shell one-off\" [label=\"clearly one-time\"];\n}\n```\n\n| Rationalization                                    | Reality                                                                                       |\n| -------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| \"I'll just try running it natively\"                | If it's not on PATH, it's not installed. Add it to the flake or use `nix shell`. Never guess. |\n| \"`nix shell` \u002F `nix run` is faster than the flake\" | 30 seconds now vs the same missing-tool failure next session. Install it.                     |\n| \"Let me ask the OPERATOR first\"                    | Permanent is the default for recurring tools. Only ask for genuinely ambiguous cases.         |\n| \"I don't know the nixpkgs package name\"            | Run `nix search nixpkgs \u003Cquery>` to find it. Never skip installation because of this.         |\n\n### Adding Packages\n\nEdit `$WORKSPACE\u002Fshell\u002Fflake.nix`, add to the `paths` list, then rebuild:\n\n    paths = with pkgs; [\n      # ... existing packages ...\n      nodejs\n    ];\n\n    ghost shell rebuild\n\n### Finding Package Names\n\n    nix search nixpkgs \u003Cquery>\n\nPackage names in nixpkgs sometimes differ from the command name. Always verify with\n`nix search` before editing the flake.\n\n### One-Off Tool Use (Exception)\n\nFor genuinely one-time tools -- a single-use converter, a quick format check:\n\n    nix shell nixpkgs#\u003Cpackage> --command \u003Ctool> [args]\n\nIf the tool ends up being used more than once, stop and add it to the flake.\n\n### Updating Shell Tools\n\nPull the latest nixpkgs (updates git, python, etc. -- NOT ghost):\n\n    nix flake update --flake $WORKSPACE\u002Fshell\u002F\n    ghost shell rebuild\n\n### Workspace Flake Architecture\n\n`$WORKSPACE\u002Fshell\u002Fflake.nix` defines the shell tools as a `buildEnv` package. At daemon\nboot, `nix build` creates a merged store path whose `bin\u002F` is prepended to PATH.\n\nThe ghost binary is NOT in this flake -- it is installed system-wide via\n`nix profile install` and available on PATH via `~\u002F.nix-profile\u002Fbin\u002F`.\n\n## Self-Update\n\nUpdate and restart GHOST:\n\n    ghost update                     # latest release\n    ghost update --from-source       # build from main\n    ghost update --version v0.3.0    # specific tag\n\nThis swaps the ghost binary in the nix profile and reboots the daemon. Shell tools are\nNOT affected -- they come from the workspace flake.\n\nRun `ghost update` **in the background**, then tell the OPERATOR there will be a brief\ndowntime while restarting.\n\n## Nix Garbage Collection\n\nReclaim disk space when store usage is high:\n\n    nix-collect-garbage -d\n    ghost version   # verify ghost still works after GC\n\n## Additional References\n\n- **`references\u002Fservices.md`** -- health check endpoints, troubleshooting, log commands\n- **`references\u002Fobservability.md`** -- SigNoz traces, metrics, and logs via\n  OpenTelemetry\n- **`references\u002Ftailscale.md`** -- secure remote access to GHOST services over Tailscale\n","# System Management\n\nManage GHOST's configuration, providers, embedded documentation, shell environment,\nservices, and self-update mechanism.\n\n## Self-Documentation\n\nGHOST bundles its own documentation into the binary. On every daemon boot these docs are\nextracted to `$WORKSPACE\u002Freferences\u002Fghost\u002Fdocs\u002F` and indexed as references under the\ntopic `ghost\u002Fdocs`.\n\n**When the OPERATOR asks how a GHOST feature works, always search the embedded docs\nbefore answering.** Use the `knowledge_search` tool:\n\n```\nknowledge_search(query=\"\u003Cwhat the OPERATOR asked about>\", topic=\"ghost\", categories=[\"references\"])\n```\n\nTopic prefix matching means `topic=\"ghost\"` finds everything under `ghost\u002Fdocs` too. Use\na specific query — `\"compaction threshold\"` not `\"compaction\"`.\n\nIf `knowledge_search` returns nothing useful, read the file directly:\n\n    $WORKSPACE\u002Freferences\u002Fghost\u002Fdocs\u002F\n\nKey doc paths for common questions:\n\n| Topic              | Doc path (under `references\u002Fghost\u002Fdocs\u002F`) |\n| ------------------ | ----------------------------------------- |\n| Config options     | `getting-started\u002Fconfiguration.md`        |\n| Providers & models | `ghost\u002Fproviders.md`                      |\n| Workspace layout   | `getting-started\u002Fworkspace.md`            |\n| Services setup     | `getting-started\u002Fservices.md`             |\n| Knowledge system   | `knowledge\u002F`                              |\n| Agents & cron      | `agents\u002F`                                 |\n| Skills             | `skills-and-tools\u002F`                       |\n| Sessions & chat    | `chat\u002F`                                   |\n| CLI reference      | `reference\u002Fcli.md`                        |\n\n| Rationalization                  | Reality                                                                                  |\n| -------------------------------- | ---------------------------------------------------------------------------------------- |\n| \"I know how this feature works\"  | Training data may be stale. The embedded docs reflect the running version. Search first. |\n| \"I'll just read the source code\" | Docs are faster and written for explanation. Read source only if docs don't answer it.   |\n\n## Configuration\n\n### File Locations\n\n- **Settings**: `~\u002F.config\u002Fghost\u002Fconfig.toml` (override: `GHOST_CONFIG_DIR` env var)\n- **Secrets**: `~\u002F.config\u002Fghost\u002F.env` — API keys, bot tokens. Never put secrets in\n  config.toml.\n\n### Reading & Writing Config\n\n```\nghost config get \u003Ckey>              # read a value (defaults applied)\nghost config set \u003Ckey> \u003Cvalue>      # write a value (validates before saving)\nghost config reload                 # signal daemon to pick up changes (SIGHUP)\n```\n\nKeys use **dot-notation** for nested values:\n\n```\nghost config get models.primary.model\nghost config set models.primary.model \"anthropic\u002Fclaude-sonnet-4\"\nghost config set compaction.threshold 0.85\nghost config set web.search_max_results 10\nghost config reload\n```\n\nThe `set` command parses TOML syntax — numbers, booleans, strings, and inline tables all\nwork. Model aliases require both `provider` and `model` keys.\n\n### Decision: How to Change Config\n\n```dot\ndigraph config_decision {\n    \"OPERATOR wants a change\" [shape=diamond];\n    \"Single setting?\" [shape=diamond];\n    \"New provider or full reconfigure?\" [shape=diamond];\n    \"Secret (API key, token)?\" [shape=diamond];\n\n    \"ghost config set + reload\" [shape=box];\n    \"ghost init (re-run wizard)\" [shape=box];\n    \"Edit ~\u002F.config\u002Fghost\u002F.env\" [shape=box];\n\n    \"OPERATOR wants a change\" -> \"Secret (API key, token)?\";\n    \"Secret (API key, token)?\" -> \"Edit ~\u002F.config\u002Fghost\u002F.env\" [label=\"yes\"];\n    \"Secret (API key, token)?\" -> \"Single setting?\" [label=\"no\"];\n    \"Single setting?\" -> \"ghost config set + reload\" [label=\"yes\"];\n    \"Single setting?\" -> \"New provider or full reconfigure?\" [label=\"multiple\"];\n    \"New provider or full reconfigure?\" -> \"ghost init (re-run wizard)\" [label=\"yes\"];\n    \"New provider or full reconfigure?\" -> \"ghost config set + reload\" [label=\"just a few keys\"];\n}\n```\n\n### Hot-Reload vs Restart\n\nMost settings take effect after `ghost config reload`. A few require a full daemon\nrestart (`ghost reboot`):\n\n| Requires restart                                    | Hot-reloadable                                |\n| --------------------------------------------------- | --------------------------------------------- |\n| `workspace` (directory path)                        | `models.*.model`, `models.*.context_window`   |\n| `embeddings.dimension` (invalidates stored vectors) | `timing.*` (idle, scheduler tick)             |\n| `discord.enabled` (interface toggle)                | `compaction.*` (threshold, limits)            |\n|                                                     | `web.*` (search provider, results, crawl URL) |\n|                                                     | `docling.*` (URL, timeout)                    |\n|                                                     | `coding.model`                                |\n|                                                     | `debug.*` (request saving)                    |\n|                                                     | `discord.allowed_user_id`                     |\n|                                                     | `embeddings.url`, `embeddings.model`          |\n\n### Key Config Reference\n\nFor the full reference, search the embedded docs:\n\n```\nknowledge_search(query=\"config.toml reference\", topic=\"ghost\", categories=[\"references\"])\n```\n\nQuick reference for common keys:\n\n| Key                              | Example value                            | What it controls                        |\n| -------------------------------- | ---------------------------------------- | --------------------------------------- |\n| `models.default`                 | `\"primary\"` or `[\"primary\", \"fallback\"]` | Default model alias (or fallback chain) |\n| `models.\u003Calias>.provider`        | `\"openrouter\"`                           | Provider backend for this alias         |\n| `models.\u003Calias>.model`           | `\"anthropic\u002Fclaude-sonnet-4\"`            | Model ID at the provider                |\n| `models.\u003Calias>.context_window`  | `200000`                                 | Token limit for this model              |\n| `models.vision`                  | `\"fast\"`                                 | Model alias used for vision\u002FPDF tasks   |\n| `discord.allowed_user_id`        | `\"123456789\"`                            | OPERATOR's Discord user ID              |\n| `embeddings.url`                 | `\"http:\u002F\u002F127.0.0.1:11434\"`               | Embedding endpoint (Ollama)             |\n| `embeddings.model`               | `\"qwen3-embedding:8b\"`                   | Embedding model name                    |\n| `timing.reflection_idle_minutes` | `10`                                     | Minutes idle before reflection          |\n| `compaction.threshold`           | `0.90`                                   | Compact at this % of context window     |\n| `web.search.provider`            | `\"brave\"` or `\"searxng\"`                 | Web search backend                      |\n| `debug.save_requests`            | `false`                                  | Save raw LLM request\u002Fresponse dumps     |\n\n| Rationalization                             | Reality                                                                         |\n| ------------------------------------------- | ------------------------------------------------------------------------------- |\n| \"I'll just edit config.toml directly\"       | Use `ghost config set` — it validates before writing and catches syntax errors. |\n| \"I need to restart for this to take effect\" | Most settings are hot-reloadable. Check the table above.                        |\n| \"I don't know what config keys exist\"       | Search embedded docs: `knowledge_search(query=\"configuration\", topic=\"ghost\")`  |\n\n## Provider Management\n\n### Supported Providers\n\n| Provider     | Config value   | Auth              | Env var              |\n| ------------ | -------------- | ----------------- | -------------------- |\n| OpenRouter   | `openrouter`   | API key           | `OPENROUTER_API_KEY` |\n| Kimi Code    | `kimi_code`    | API key           | `KIMI_API_KEY`       |\n| Anthropic    | `anthropic`    | Claude Code OAuth | —                    |\n| OpenAI OAuth | `openai_oauth` | Device code flow  | —                    |\n\nUse the config values from this table exactly — they match the `ProviderKind` enum.\n\n### Common Operations\n\n**View current provider:**\n\n    ghost config get models.primary\n\n**Switch model (same provider):**\n\n    ghost config set models.primary.model \"new-model-id\"\n    ghost config reload\n\n**Add a new provider** — re-run the setup wizard. It validates credentials with a real\nAPI call before saving:\n\n    ghost init --provider openrouter --api-key sk-... --model anthropic\u002Fclaude-sonnet-4 --context-window 200000\n\nPass `--start` to restart services after. If run without flags, `ghost init` enters\ninteractive mode and prompts for each value.\n\n**Change an API key:**\n\nEdit `~\u002F.config\u002Fghost\u002F.env` directly, then:\n\n    ghost config reload\n\n**Validate setup:**\n\n    ghost status\n\nThis checks config validity and probes every configured service endpoint.\n\n### Decision: When to Use `ghost init` vs `ghost config set`\n\n```dot\ndigraph provider_decision {\n    \"Provider change\" [shape=diamond];\n    \"Same provider, different model?\" [shape=diamond];\n    \"New provider entirely?\" [shape=diamond];\n\n    \"ghost config set + reload\" [shape=box];\n    \"ghost init\" [shape=box];\n\n    \"Provider change\" -> \"Same provider, different model?\";\n    \"Same provider, different model?\" -> \"ghost config set + reload\" [label=\"yes\"];\n    \"Same provider, different model?\" -> \"New provider entirely?\" [label=\"no\"];\n    \"New provider entirely?\" -> \"ghost init\" [label=\"yes — validates credentials\"];\n}\n```\n\nUse `ghost init` for new providers because it tests the connection before saving. For\nsimple model swaps on an existing provider, `ghost config set` + `reload` is faster.\n\n| Rationalization                            | Reality                                                                                                     |\n| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |\n| \"I'll guess the provider name\"             | Use the exact `ProviderKind` values from the table: `openrouter`, `kimi_code`, `openai_oauth`, `anthropic`. |\n| \"I can set the API key in config.toml\"     | API keys go in `.env`, never in config.toml. Config is not secret.                                          |\n| \"I'll skip validation, it's probably fine\" | `ghost init` validates with a real API call. Use it for new providers. `ghost status` for existing ones.    |\n\n## Services\n\nGHOST's infrastructure has two tiers: **native services** (ghost-daemon, llama-server,\ndocling-serve) managed by the OS process supervisor, and **container services**\n(searxng, crawl4ai, chrome) managed by Podman\u002FDocker Compose.\n\nPrefer `ghost` CLI commands over raw systemctl\u002Flaunchctl\u002Fcompose:\n\n```\nghost start                   # start all services and the daemon\nghost stop                    # stop the daemon and all services\n\nghost services list           # show registered services and their state\nghost services add            # register a new service (interactive)\nghost services remove \u003Cname>  # unregister a service\nghost services update         # pull updates and restart all services\nghost services status         # check process-level status\n\nghost status                  # config validity + HTTP health probes\n```\n\nTo reconfigure ports, credentials, or which services are enabled: `ghost init`.\n\nFor health check endpoints, troubleshooting, and log commands, consult\n**`references\u002Fservices.md`**.\n\n## Shell Environment\n\n### Default: Install Permanently\n\nWhen a tool is needed, decide based on expected reuse:\n\n- **Recurring tool** (build tool, linter, language runtime, CLI used across sessions) --\n  add to the flake permanently.\n- **Rare\u002Fone-off binary** (single-use converter, one-time migration tool) -- use\n  `nix shell` for a temporary run.\n\nWhen unsure, install permanently. Removing a package later is trivial; losing time to a\nmissing tool in the next session is not.\n\n```dot\ndigraph shell_decision {\n    \"Need a CLI tool\" [shape=diamond];\n    \"Recurring or likely reused?\" [shape=diamond];\n    \"Add to flake\" [shape=box];\n    \"nix shell one-off\" [shape=box];\n\n    \"Need a CLI tool\" -> \"Recurring or likely reused?\";\n    \"Recurring or likely reused?\" -> \"Add to flake\" [label=\"yes or unsure\"];\n    \"Recurring or likely reused?\" -> \"nix shell one-off\" [label=\"clearly one-time\"];\n}\n```\n\n| Rationalization                                    | Reality                                                                                       |\n| -------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| \"I'll just try running it natively\"                | If it's not on PATH, it's not installed. Add it to the flake or use `nix shell`. Never guess. |\n| \"`nix shell` \u002F `nix run` is faster than the flake\" | 30 seconds now vs the same missing-tool failure next session. Install it.                     |\n| \"Let me ask the OPERATOR first\"                    | Permanent is the default for recurring tools. Only ask for genuinely ambiguous cases.         |\n| \"I don't know the nixpkgs package name\"            | Run `nix search nixpkgs \u003Cquery>` to find it. Never skip installation because of this.         |\n\n### Adding Packages\n\nEdit `$WORKSPACE\u002Fshell\u002Fflake.nix`, add to the `paths` list, then rebuild:\n\n    paths = with pkgs; [\n      # ... existing packages ...\n      nodejs\n    ];\n\n    ghost shell rebuild\n\n### Finding Package Names\n\n    nix search nixpkgs \u003Cquery>\n\nPackage names in nixpkgs sometimes differ from the command name. Always verify with\n`nix search` before editing the flake.\n\n### One-Off Tool Use (Exception)\n\nFor genuinely one-time tools -- a single-use converter, a quick format check:\n\n    nix shell nixpkgs#\u003Cpackage> --command \u003Ctool> [args]\n\nIf the tool ends up being used more than once, stop and add it to the flake.\n\n### Updating Shell Tools\n\nPull the latest nixpkgs (updates git, python, etc. -- NOT ghost):\n\n    nix flake update --flake $WORKSPACE\u002Fshell\u002F\n    ghost shell rebuild\n\n### Workspace Flake Architecture\n\n`$WORKSPACE\u002Fshell\u002Fflake.nix` defines the shell tools as a `buildEnv` package. At daemon\nboot, `nix build` creates a merged store path whose `bin\u002F` is prepended to PATH.\n\nThe ghost binary is NOT in this flake -- it is installed system-wide via\n`nix profile install` and available on PATH via `~\u002F.nix-profile\u002Fbin\u002F`.\n\n## Self-Update\n\nUpdate and restart GHOST:\n\n    ghost update                     # latest release\n    ghost update --from-source       # build from main\n    ghost update --version v0.3.0    # specific tag\n\nThis swaps the ghost binary in the nix profile and reboots the daemon. Shell tools are\nNOT affected -- they come from the workspace flake.\n\nRun `ghost update` **in the background**, then tell the OPERATOR there will be a brief\ndowntime while restarting.\n\n## Nix Garbage Collection\n\nReclaim disk space when store usage is high:\n\n    nix-collect-garbage -d\n    ghost version   # verify ghost still works after GC\n\n## Additional References\n\n- **`references\u002Fservices.md`** -- health check endpoints, troubleshooting, log commands\n- **`references\u002Fobservability.md`** -- SigNoz traces, metrics, and logs via\n  OpenTelemetry\n- **`references\u002Ftailscale.md`** -- secure remote access to GHOST services over Tailscale\n",{"name":5,"description":7},"main","083d96429a2d05526f8a294b83c74f0336670def","assets\u002Fskills\u002Fsystem-management",0,"https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST","https:\u002F\u002Fgithub.com\u002Fmrtolkien","https:\u002F\u002Fblog.tolki.dev","Data Engineer \u002F Esports \u002F Keyboards","2026-04-24 15:41:08",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add mrtolkien\u002FGHOST --skill system-management",{"tool":59,"command":60},"bunx","bunx skills add mrtolkien\u002FGHOST --skill system-management",{"tool":62,"command":63},"pnpm","pnpm dlx skills add mrtolkien\u002FGHOST --skill system-management","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsystem-management\u002Fskill.md",true,[67,73,77],{"path":68,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":72},"references\u002Fobservability.md","REFERENCE","参考文档",3695,"https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsystem-management\u002Freferences\u002Fobservability.md",{"path":74,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":75,"sourceHtmlUrl":76},"references\u002Fservices.md",1575,"https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsystem-management\u002Freferences\u002Fservices.md",{"path":78,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Ftailscale.md",3551,"https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsystem-management\u002Freferences\u002Ftailscale.md",[82,108,126,135,146,157],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":101,"publishedAt":39},"01M6CS5XTK2884R9HE15YR8YZM","writing-skills","Use when creating new skills, editing existing skills, or verifying skills work before deployment","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Fwriting-skills\u002Fskill.md",[88,93,96],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":94,"categoryName":95,"taxonomyType":91,"taxonomyTypeDesc":92},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[102,103,104,105,106,107,27],"writing","writing skills","deployment","coding","work","editing",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":116,"publishedAt":39},"01M6CS5V737R1DVB3TZEK0C6WT","writing-plans","Use when you have a spec or requirements for a multi-step task, before touching code. Write comprehensive implementation plans assuming the engineer has zero context for our codebase and questionable taste.","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Fwriting-plans\u002Fskill.md",[114,115],{"categoryNo":94,"categoryName":95,"taxonomyType":91,"taxonomyTypeDesc":92},{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},[117,102,105,118,119,120,121,122,27,123,124,125],"writing plans","spec","code","ZeRO","write","context","engineer","implementation","task",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":39},"01M6CS5S5S0YY56686G5CQ0WMP","verification","Use when about to claim work is complete, fixed, or passing, before committing or creating PRs. Requires running verification commands and confirming output before making any success claims. Evidence before assertions, always.","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Fverification\u002Fskill.md",[],[128,106,27,105,133,134],"evidence","claim",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":142,"publishedAt":39},"01M6CS5PD2ZSFWYRDZSACNTAJY","tdd","Use when implementing any feature or bugfix, before writing implementation code. Write the test first. Watch it fail. Write minimal code to pass.","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Ftdd\u002Fskill.md",[141],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},[137,124,143,144,27,102,145,119,105,121],"minimal","first","test",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":153,"publishedAt":39},"01M6CS5K5WE2SHF1YV8D9C4C77","systematic-debugging","Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Fsystematic-debugging\u002Fskill.md",[152],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},[154,38,145,105,155,27,156],"systematic debugging","behavior","bug",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":163,"publishedAt":39},"01M6CS5FPYWZHHG4X0GQHR8CKT","subagent-development","Use when executing implementation plans with independent tasks in the current session. Dispatch a fresh subagent per task, with two-stage review after each — spec compliance review first, then code quality review. Keeps context clean and quality high.","https:\u002F\u002Fgithub.com\u002Fmrtolkien\u002FGHOST\u002Fblob\u002Fmain\u002Fassets\u002Fskills\u002Fsuperpowers\u002Fsubagent-development\u002Fskill.md",[],[164,165,166,167,118,168,169,119,170,144,105,171,122,172,27,173,124,125,174,175],"subagent development","subagent","development","clean","code quality","tasks","compliance","quality","session","dispatch","quality review","review"]