appydave-tools 0.84.0 → 0.85.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbde49937db92444ee47416c1fbd53d0cd3ca6c99bc65b30e30a58cf2490facc
4
- data.tar.gz: 1807239701f53c00bd7e692c51e6792056b2e951d0b71720059fdd5c5fbd4414
3
+ metadata.gz: 9bdf9ee95d2587f01a5939fc780148a9da0bdc06c5acac865dc36077d34181c9
4
+ data.tar.gz: 54f137a91341ec1b9487a7dc68fd44c837d2a53d52181dd7681d0f1a11135062
5
5
  SHA512:
6
- metadata.gz: be1b84a9fb1b45b7377c8cc0e0371f234b5b56e96f23a44f1733e6face17c489a288bd3f8128a5e8548eb09247ff3deffd38144eb6480214b5ba8401406bf022
7
- data.tar.gz: e3cffdedb85686158bc251361f04b0b2ea44f354f472968efd92bf84c165dd1aa69ca37aa0e1105c191b5f84d70ccccbf0ed7e9418e0e194dbf1a1dceca0bfd8
6
+ metadata.gz: 216862256621db14b1384bfdef38d34749f734601d9c382497a0193240eda80227cffb2940daa8326f30154bfb48b2404af48e5ccf9f54f52d1a7042721b7dae
7
+ data.tar.gz: 205f2cd87df58e2c12b426aceea29c7c1dd88e52622e5fff889d8d655f1ad572621d795718f5ea0d7e603663cbc3acd2f5ac1a04f765144e5b6de3dc9361abdb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [0.84.0](https://github.com/appydave/appydave-tools/compare/v0.83.0...v0.84.0) (2026-04-05)
2
+
3
+
4
+ ### Features
5
+
6
+ * add jump query subcommand for scriptable location lookup ([fe3429b](https://github.com/appydave/appydave-tools/commit/fe3429bc08ccb6167c1a0575c2154852fba29ccd))
7
+
1
8
  # [0.83.0](https://github.com/appydave/appydave-tools/compare/v0.82.0...v0.83.0) (2026-04-04)
2
9
 
3
10
 
data/CLAUDE.md CHANGED
@@ -27,7 +27,7 @@ Two-phase validation for the 75-commit DAM enhancement sprint (9e49668 → 4228b
27
27
  - **Shareable individually** - Tools can be featured in standalone videos
28
28
  - **Language flexible** - Currently Ruby, could be rewritten if needed
29
29
 
30
- **System context**: See [CONTEXT.md](CONTEXT.md) for purpose, domain concepts, design rationale, and scope boundaries.
30
+ **System context**: See [CONTEXT.md](CONTEXT.md) for purpose, core abstractions, key workflows, design decisions, non-obvious constraints, expert mental model, scope limits, and failure modes.
31
31
 
32
32
  ## Documentation Discovery Protocol
33
33
 
data/CONTEXT.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- generated: 2026-04-03
2
+ generated: 2026-04-05
3
3
  generator: system-context
4
4
  status: snapshot
5
5
  sources:
@@ -8,37 +8,147 @@ sources:
8
8
  - lib/appydave/tools.rb
9
9
  - lib/appydave/tools/dam/brand_resolver.rb
10
10
  - lib/appydave/tools/dam/project_resolver.rb
11
+ - lib/appydave/tools/jump/config.rb
11
12
  - lib/appydave/tools/jump/commands/generate.rb
12
- - docs/dam/batch-s3-listing-requirements.md
13
- - CHANGELOG.md (versions 0.76.0-0.77.7)
13
+ - lib/appydave/tools/brain_context/brain_finder.rb
14
+ - lib/appydave/tools/brain_context/options.rb
15
+ - lib/appydave/tools/app_context/app_finder.rb
16
+ - lib/appydave/tools/app_context/globs_loader.rb
17
+ - lib/appydave/tools/app_context/options.rb
18
+ - lib/appydave/tools/configuration/models/settings_config.rb
19
+ - lib/appydave/tools/configuration/example_installer.rb
20
+ - lib/appydave/tools/zsh_history/config.rb
21
+ - lib/appydave/tools/zsh_history/filter.rb
22
+ - docs/planning/multi-user-support.md
23
+ - docs/planning/query-apps-design.md
24
+ - docs/planning/query-skills-plan.md
25
+ - CHANGELOG.md
26
+ - context.globs.json
14
27
  regenerate: "Run /appydave:system-context in the repo root"
15
28
  ---
16
29
 
17
30
  # AppyDave Tools — System Context
18
31
 
19
32
  ## Purpose
20
- Eliminate repetitive manual tasks from YouTube content creation workflows by bundling single-purpose CLI utilities that operate independently on video projects, metadata, and assets.
33
+ Eliminate repetitive manual tasks from a solo YouTube content creator's workflow by bundling single-purpose CLI utilities for file discovery, asset management, knowledge querying, and LLM context assembly — in one Ruby gem that multiple developers can independently configure and install.
21
34
 
22
- ## Domain Concepts
23
- - **Brand** — A business entity that owns video projects (AppyDave, VOZ, SupportSignal, etc.). Shortcuts (ad, joy, ss) resolve to brand keys (appydave, beauty-and-joy, supportsignal) in configs.
24
- - **Project** — A discrete video deliverable. Named by pattern: FliVideo uses short codes (b65 expands to b65-guy-monroe-marketing-plan), Storyline uses full names (boy-baker). Projects contain assets, metadata, and source files.
25
- - **Digital Asset Management (DAM)** — Hybrid 3-tier storage: local working copies → S3 staging for collaboration (90-day lifecycle) → SSD archive for long-term cold storage. Orchestrates file sync and lifecycle across tiers.
26
- - **Project Naming Patterns** — FliVideo: `b<num>` (short) expands to `b<num>-*` full name. Patterns like `b6*` match b60-b69. Storyline uses exact full names (no expansion).
27
- - **Configuration-driven Architecture** — JSON configs (settings, channels, brands) stored in `~/.config/appydave/` per developer; secrets (.env) gitignored. Enables team collaboration: shared structure, per-dev customization.
28
- - **Multi-channel YouTube Management** — Handles multiple YouTube channels (each with code, name, handle, locations). Single tool manages metadata updates across channels.
35
+ ## Core Abstractions
36
+
37
+ - **Location** — A named, user-specific folder registered in `~/.config/appydave/locations.json`. Every query tool (jump, query_apps, query_brain, query_omi) uses locations as its resolution anchor. A location has a `key` (canonical name), `path` (machine-specific), optional `jump` alias, and optional `context` pointer to `CONTEXT.md`. Without locations, no tool can find anything.
38
+
39
+ - **Query Ecosystem** — Three tools that each output file paths on stdout: `query_brain` (finds second-brain knowledge files via `brains-index.json`), `query_omi` (finds OMI wearable transcript sessions), and `query_apps` (finds project source files via `context.globs.json`). All three feed into `llm_context`, which assembles the paths into formatted content for an LLM. The tools are composable by design — the output of any query tool can be piped to `llm_context --stdin`.
40
+
41
+ - **DAM (Digital Asset Management)** — Hybrid 3-tier storage for video project files: local working copies → S3 staging for team collaboration (90-day lifecycle) → SSD for cold archive. Operates on whole project directories as atomic units. Multi-tenant: a single tool manages assets for 6 brands (appydave, voz, aitldr, kiros, joy, ss), each with independent S3 buckets and SSD paths.
42
+
43
+ - **Brand/Project Resolution** — A two-step lookup used by DAM. `BrandResolver` maps shorthand brand codes (`ad`, `ss`) to config keys (`appydave`, `supportsignal`). `ProjectResolver` maps short codes (`b65`) to full project names (`b65-guy-monroe-marketing-plan`) using glob expansion. Decouples what users type from what the filesystem requires.
44
+
45
+ - **context.globs.json** — A sidecar file generated by the `system-context` skill alongside each project's `CONTEXT.md`. Contains named glob patterns (`docs`, `services`, `types`), aliases (`backend` → services + routes), and composites (`understand` → context + docs + types + config). `query_apps` reads this file; `GlobsLoader` handles 3-tier resolution (direct name → alias → composite → substring fuzzy fallback). Projects without this file are invisible to `query_apps`.
46
+
47
+ - **Settings Config** — Per-user JSON at `~/.config/appydave/settings.json`. Provides the canonical store for machine-specific paths that tools resolve at runtime: `video-projects-root`, `brains-root-path`, `omi-directory-path`, `aliases-output-path`. Tools read settings via `Configuration::Config.settings.get(key)` and fall back to hardcoded defaults if the key is absent.
48
+
49
+ ## Key Workflows
50
+
51
+ ### Assemble LLM Context from a Project
52
+ 1. User identifies the project they want context for (e.g., `flihub`)
53
+ 2. `query_apps flihub --glob understand` resolves the app via `locations.json`, reads `flihub/context.globs.json`, and expands the `understand` composite (context + docs + types + config) to a list of absolute file paths
54
+ 3. Paths are piped to `llm_context --stdin -f content --smart`
55
+ 4. `llm_context` reads each file, formats it with headers, estimates token count, and routes output to clipboard (≤100k tokens) or a temp file (larger)
56
+ 5. User pastes the assembled content into their LLM session
57
+
58
+ ### Query the Second Brain for a Topic
59
+ 1. User knows a topic or brain name (e.g., `paperclip`, `agent-systems`)
60
+ 2. `query_brain --find paperclip` loads `brains-index.json` (pre-built by `build_brain_index.py`), resolves the name through 4 tiers (exact key → alias → substring → tag match), and returns absolute paths to brain files
61
+ 3. Optionally `--files-only` to exclude `INDEX.md`; `--meta` to return JSON instead of paths
62
+ 4. User pipes to `llm_context --stdin -f content --smart` or reviews paths directly
63
+
64
+ ### Video Project Collaboration via DAM
65
+ 1. Videographer has edited files in a local video project (e.g., `b65-guy-monroe-marketing-plan`)
66
+ 2. `dam s3-up appydave b65` resolves brand → config → S3 bucket, computes MD5 checksums for all files, uploads only changed files to S3
67
+ 3. Collaborator runs `dam s3-down appydave b65` on their machine — same MD5 logic skips unchanged files
68
+ 4. When the project is complete, `dam archive appydave b65` moves it to the external SSD; S3 lifecycle policy removes it after 90 days
69
+
70
+ ### Onboard a New Developer (Multi-user)
71
+ 1. New user runs `gem install appydave-tools`
72
+ 2. `ad_config -c` creates the `~/.config/appydave/` directory structure with all config templates from the gem's bundled `config/examples/*.example.*` files (via `ExampleInstaller`)
73
+ 3. User edits `settings.json` to set their machine-specific paths (`video-projects-root`, `brains-root-path`, etc.)
74
+ 4. User populates `locations.json` with their project paths and runs `jump generate` to produce shell aliases
75
+ 5. User sources the generated aliases file from their `.zshrc` to activate `j<alias>` navigation
76
+
77
+ ### ZSH History Crash Recovery
78
+ 1. After a terminal crash or mid-session confusion, user runs `zsh_history --profile crash-recovery`
79
+ 2. `ZshHistory::Filter` loads config from `~/.config/appydave/zsh_history/` — base exclude patterns (noise) plus profile-specific include/exclude patterns
80
+ 3. Commands are classified into `wanted` (matched include patterns), `unwanted` (matched exclude), or `unsure` (matched neither)
81
+ 4. User reviews the `wanted` list to reconstruct what they were working on before the crash
29
82
 
30
83
  ## Design Decisions
31
- - **Single consolidated repository** — instead of separate gems per tool. Reduces maintenance overhead, enables code reuse, allows individual tools to be featured in standalone tutorials.
32
- - **Single-purpose tools that operate independently** each CLI does one thing (llm_context, youtube_manager, dam, etc.). Prevents feature creep, keeps coupling low, enables composition.
33
- - **Configuration as data** JSON files enable team sharing of project structure + team-specific path customization in .env. Separates secrets (API keys) from configuration (paths, channels).
34
- - **Hybrid storage lifecycle** S3 for short-term collaboration, SSD for archive. Balances cost (S3 pay-per-access), availability (local for daily work), and durability (SSD backup).
35
- - **Brand/Project resolution layer** — BrandResolver + ProjectResolver decouple CLI input (shortcuts like ad, b65) from system state (config keys, full paths). Users type short codes; system maps to canonical names.
36
- - **Parallel status checking**`dam list <brand> --s3` parallelizes git and S3 status checks instead of N sequential API calls. Reduces list latency from 3-5s to <1s.
84
+
85
+ - **Single consolidated repository** instead of separate gems per tool. Reduces maintenance overhead, allows code reuse (e.g., `BrainContextOptions` shared by both `query_brain` and `query_omi`), and enables individual tools to be featured in standalone tutorials without needing cross-gem dependency management.
86
+ - *Alternative considered*: One gem per tool
87
+ - *Why rejected*: Separate gems double the CI setup, versioning work, and gem publish steps per tool added; the tools share too much infrastructure (config, settings, output handling)
88
+
89
+ - **Configuration as data in `~/.config/appydave/`** JSON files per user, secrets in `.env`, structure in JSON. This means the gem can be shared via RubyGems.org with zero David-specific paths baked in. Each user configures their own machine independently.
90
+ - *Alternative considered*: Bundled config files committed to the repo
91
+ - *Why rejected*: Binds the gem to one user's machine layout; makes it impossible for Lars or anyone else to install without overwriting David's paths
92
+
93
+ - **Query tools output file paths, not content** — `query_brain`, `query_omi`, `query_apps` all emit one path per line. This makes them pipe-composable with `llm_context`, `xargs`, or any Unix tool without intermediate temp files.
94
+ - *Alternative considered*: Query tools output content directly
95
+ - *Why rejected*: Conflates discovery (which files?) with assembly (what format?); forces the query tool to duplicate output logic that `llm_context` already owns
96
+
97
+ - **context.globs.json as a sidecar file** — Named glob patterns live in each project root, not in a central registry. This means each project self-describes its own structure; no central config needs updating when a project is restructured.
98
+ - *Alternative considered*: Central registry mapping project keys to glob patterns
99
+ - *Why rejected*: Central registry goes stale as projects evolve; a sidecar file is updated when `system-context` is re-run in that project
100
+
101
+ - **Hybrid S3 + SSD storage** for DAM. S3 handles team collaboration (anyone with credentials can push/pull); SSD handles archival (local, fast, no recurring cost for cold files).
102
+ - *Alternative considered*: S3-only or git-lfs
103
+ - *Why rejected*: S3-only means paying for cold storage indefinitely; git-lfs can't handle 50GB+ video files with binary diffs
104
+
105
+ - **MD5-based sync** instead of timestamp comparison in DAM. MD5 checksums correctly detect when a file has been re-encoded identically (same content, new timestamp) — common when re-exporting video.
106
+ - *Alternative considered*: rsync with `--update` (timestamp-based)
107
+ - *Why rejected*: Video export tools reset timestamps on every render even for identical output; timestamp sync would re-upload unnecessarily every time
108
+
109
+ ## Non-obvious Constraints
110
+
111
+ - **`query_brain` requires `brains-index.json` to exist** — it does not scan the brains folder directly. The index is built by a separate Python script (`build_brain_index.py`) in the `brain-librarian` skill. If the index is missing or stale, `query_brain` raises a descriptive error pointing to the build command. A new developer who hasn't run `brain-librarian` will see this error immediately.
112
+
113
+ - **`query_apps` requires `context.globs.json` in each project root** — it does not fall back to filesystem scanning. A project that has never had `/system-context` run against it is simply invisible to `query_apps --list-apps`. The `--list-apps` command will show zero results for that project even if `locations.json` knows about it.
114
+
115
+ - **`brains-root-path` and `omi-directory-path` in settings.json override the hardcoded defaults** — but silently do nothing if the key is missing. `BrainContextOptions` falls back to `~/dev/ad/brains` and `~/dev/raw-intake/omi` respectively. A developer on a different machine layout must set these keys explicitly; there is no warning if the default paths don't exist.
116
+
117
+ - **Jump aliases require manual shell sourcing** — `jump generate` writes a `.aliases` file (path configured by `aliases-output-path` in settings.json) but does NOT source it automatically. The user must add `source <path>` to their `.zshrc`. Running `jump generate` without sourcing produces no visible `j<alias>` commands in the current shell.
118
+
119
+ - **DAM brand resolution is case-sensitive at the config level** — `BrandResolver` lowercases input before lookup, so `vat s3-up AppyDave b65` works. But `settings.json` and `channels.json` keys must be lowercase. A brand key `AppyDave` in the config will never match.
120
+
121
+ - **ZshHistory filter applies exclude before include** — a command that matches both an exclude pattern and an include pattern is classified as `unwanted`. Exclude wins. This matters when writing profile-specific patterns: a general exclude like `^cd` will suppress `^cd ~/dev` even if the include pattern explicitly lists it.
122
+
123
+ ## Expert Mental Model
124
+
125
+ - **Think of locations.json as the root of all resolution** — every query tool starts here. An expert's first debugging step when a tool can't find a project is to verify the project exists in `locations.json`, that its `path` is correct on this machine, and that `query_apps` requires a `context.globs.json` at that path. The tool chain is: `locations.json` → `context.globs.json` → filesystem. A break at any link silently returns empty results, not an error.
126
+
127
+ - **The query ecosystem is a pipeline, not a single command** — an expert treats `query_brain`, `query_omi`, `query_apps` as interchangeable producers and `llm_context` as the sole consumer. The skill layer (`/omi-query`, `/app-query`, `/brain-query`) is just documentation for Claude Code about how to invoke the producers. An expert composes them with `|` and uses `--meta` when they need to reason about what exists before deciding what to fetch.
128
+
129
+ - **Settings config is the machine-portability layer** — an expert keeps all hardcoded paths out of gem code and inside `settings.json`. When something works on David's machine but fails on Lars's, the root cause is almost always a missing or wrong key in `settings.json`. The key names are documented in `SettingsConfig` as named methods (`brains_root_path`, `omi_directory_path`, etc.) — reading that file tells you exactly what keys each tool expects.
130
+
131
+ - **ExampleInstaller is the onboarding contract** — the `config/examples/` directory inside the gem is the canonical template for a correct initial config. When adding a new config key, an expert updates both `SettingsConfig` (for named accessor) and the relevant `*.example.json` file (so new users get it on `ad_config -c`).
37
132
 
38
133
  ## Scope Limits
39
- - Does NOT edit video files directly — only manages metadata, assets, and file organization. Video editing remains in post-production tools (Premiere, DaVinci, etc.).
40
- - Does NOT provide local playback or streaming focuses on storage, sync, and metadata. Video playback via external players or YouTube.
41
- - Does NOT implement YouTube OAuth UI — wraps Google's authentication library. OAuth token generation handled by google-api-client flows, not custom UI.
42
- - Does NOT manage individual files in DAM — operates on whole project directories as atomic units. Granular file operations are external (rsync, direct S3 CLI).
43
- - Does NOT provide IDE integration for Jump tool generates shell aliases and help text. IDE navigation handled by native IDE shortcuts or external plugins.
44
- - Does NOT handle video versioning or branchingDAM is a flat archive. Version control (git) handles project versioning separately from media storage.
134
+
135
+ - Does NOT edit video files directlyonly manages metadata, assets, and file sync. Video editing remains in Premiere, DaVinci, etc.
136
+ - Does NOT implement a YouTube UI or web interface — wraps Google's youtube-api-client library for CLI metadata updates. Browsing or uploading video content requires YouTube's own interface.
137
+ - Does NOT manage individual files within a DAM project — operates on whole project directories as atomic units. Granular in-project file operations are handled by the user's editor, Finder, or direct `rsync`.
138
+ - Does NOT handle video versioning or branchingDAM is flat archive. Version control for code remains in git; media versioning is not addressed.
139
+ - Does NOT scan the brains folder directly`query_brain` reads a pre-built `brains-index.json`. Brain discovery, indexing, and metadata enrichment are the responsibility of the `brain-librarian` skill's Python scripts.
140
+ - Does NOT provide IDE integration for Jump — generates shell aliases only. IDE navigation handled by native IDE shortcuts.
141
+
142
+ ## Failure Modes
143
+
144
+ - **`query_brain` raises "brains-index.json not found"** — the pre-built brain index doesn't exist at the path configured by `brains-root-path` (or the default `~/dev/ad/brains/audit/`). Fix: run `build_brain_index.py build --all <brains-root>` from the `brain-librarian` skill. This is a loud failure with a clear message.
145
+
146
+ - **`query_apps` returns empty results silently** — the app exists in `locations.json` but has no `context.globs.json`. The tool returns `[]` without error. Fix: run `/system-context` in that project root to generate the sidecar file. Diagnosable via `query_apps --list-apps` (the app won't appear) or by checking `File.exist?(project_path + '/context.globs.json')` manually.
147
+
148
+ - **Jump aliases don't work after `jump generate`** — the `.aliases` file was written but not sourced in the current shell. Fix: add `source <aliases-output-path>` to `.zshrc` and re-open the terminal, or source it manually in the current shell. Diagnosable by running `type jad-tools` — if it says "not found", the aliases aren't loaded.
149
+
150
+ - **DAM sync uploads every file on each run** — `video-projects-root` in `settings.json` points to the wrong directory or has a trailing slash difference. `ProjectResolver` builds paths by joining the root with brand and project subdirectories; if the root is wrong, MD5 comparison reads no local files and treats everything as new. Fix: verify `settings.json` contains the correct absolute path.
151
+
152
+ - **`ad_config -c` creates empty configs but tools still error on missing keys** — `ExampleInstaller` copies `*.example.json` files from `config/examples/` into `~/.config/appydave/`, but the example files contain placeholder values like `NOT-SET` and `""`. Tools that require a specific key (e.g., `video-projects-root` for DAM, `brains-root-path` for brain query) will silently return `nil` or fall back to hardcoded defaults that may not exist on this machine. Fix: edit the installed files to set real paths.
153
+
154
+ - **ZshHistory filter classifies too many commands as `unsure`** — no configured profile exists or the profile directory is missing, causing `Filter` to fall back to built-in defaults. The defaults are tailored to David's workflow; they may not match a different developer's commands. Fix: create a custom profile in `~/.config/appydave/zsh_history/profiles/<name>/` with `include.txt` and `exclude.txt` patterns, then set `default_profile=<name>` in `config.txt`.
data/bin/configuration.rb CHANGED
@@ -29,6 +29,10 @@ OptionParser.new do |opts|
29
29
  options[:command] = :create
30
30
  end
31
31
 
32
+ opts.on('-x', '--install-examples', 'Install bundled example configs (safe — skips existing files)') do
33
+ options[:command] = :install_examples
34
+ end
35
+
32
36
  opts.on('-p', '--print [KEYS]', Array, 'Print configuration details for specified keys') do |keys|
33
37
  options[:command] = :print
34
38
  options[:keys] = keys
@@ -72,6 +76,22 @@ when :create
72
76
  puts "\n⚠️ Skipped (already exist):"
73
77
  skipped.each { |name| puts " - #{name}" }
74
78
  end
79
+ when :install_examples
80
+ Appydave::Tools::Configuration::Config.configure
81
+ installer = Appydave::Tools::Configuration::ExampleInstaller.new
82
+ result = installer.install
83
+
84
+ puts "\n✅ Installed example configurations:"
85
+ if result[:installed].any?
86
+ result[:installed].each { |name| puts " - #{name}" }
87
+ else
88
+ puts ' (none — all examples already present)'
89
+ end
90
+
91
+ if result[:skipped].any?
92
+ puts "\n⚠️ Skipped (already exist):"
93
+ result[:skipped].each { |name| puts " - #{name}" }
94
+ end
75
95
  when :print
76
96
  Appydave::Tools::Configuration::Config.configure
77
97
  Appydave::Tools::Configuration::Config.print(*options[:keys])
data/bin/query_apps.rb ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+ require 'appydave/tools'
6
+
7
+ options = Appydave::Tools::AppContext::Options.new
8
+
9
+ def setup_options(options)
10
+ OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
11
+ opts.banner = 'Usage: query_apps [APP] [options]'
12
+
13
+ opts.on('--find APP', 'Find app by key, jump alias, or substring (repeatable)') do |app|
14
+ options.app_names << app
15
+ end
16
+
17
+ opts.on('--glob NAMES', 'Glob names to resolve (comma-separated)') do |names|
18
+ options.glob_names.concat(names.split(',').map(&:strip))
19
+ end
20
+
21
+ opts.on('--pattern PATTERN', 'Filter by project pattern type (e.g., rvets, nextjs)') do |pat|
22
+ options.pattern_filter = pat
23
+ end
24
+
25
+ opts.on('--list', 'List available glob names for the specified app') do
26
+ options.list = true
27
+ end
28
+
29
+ opts.on('--list-apps', 'List all apps with context.globs.json') do
30
+ options.list_apps = true
31
+ end
32
+
33
+ opts.on('--meta', 'Return metadata as JSON instead of file paths') do
34
+ options.meta = true
35
+ end
36
+
37
+ opts.on('-d', '--debug [MODE]', %w[none info params debug],
38
+ 'Debug output level') do |level|
39
+ options.debug_level = level || 'info'
40
+ end
41
+
42
+ opts.on('-v', '--version', 'Show version') do
43
+ puts "query_apps v#{Appydave::Tools::VERSION}"
44
+ exit 0
45
+ end
46
+
47
+ opts.on('-h', '--help', 'Show this message') do
48
+ puts opts
49
+ exit 0
50
+ end
51
+ end.parse!
52
+ end
53
+
54
+ setup_options(options)
55
+
56
+ # Positional arg as app name if no --find given
57
+ options.app_names << ARGV.shift if ARGV.any? && options.app_names.empty?
58
+
59
+ finder = Appydave::Tools::AppContext::AppQuery.new(options)
60
+
61
+ if options.list_apps
62
+ require 'json'
63
+ puts JSON.pretty_generate(finder.list_apps)
64
+ elsif options.list && options.app_names.any?
65
+ require 'json'
66
+ puts JSON.pretty_generate(finder.list_globs(options.app_names.first))
67
+ elsif options.meta
68
+ require 'json'
69
+ puts JSON.pretty_generate(finder.find_meta)
70
+ else
71
+ finder.find.each { |p| puts p }
72
+ end
73
+
74
+ exit 0
@@ -0,0 +1,48 @@
1
+ {
2
+ "meta": {
3
+ "version": "1.0",
4
+ "description": "Jump locations — edit paths to match your dev folder structure, then run: jump generate"
5
+ },
6
+ "categories": {
7
+ "type": {
8
+ "description": "Kind of location",
9
+ "values": ["brand", "client", "gem", "video", "brain", "site", "tool", "config"]
10
+ },
11
+ "technology": {
12
+ "description": "Primary language/framework",
13
+ "values": ["ruby", "javascript", "typescript", "python", "astro"]
14
+ }
15
+ },
16
+ "brands": {},
17
+ "clients": {},
18
+ "locations": [
19
+ {
20
+ "key": "dev",
21
+ "path": "~/dev",
22
+ "alias": "jdev",
23
+ "description": "Root dev folder",
24
+ "type": "tool"
25
+ },
26
+ {
27
+ "key": "brain",
28
+ "path": "~/dev/brains",
29
+ "alias": "jbrain",
30
+ "description": "Second brain knowledge base",
31
+ "type": "brain"
32
+ },
33
+ {
34
+ "key": "omi",
35
+ "path": "~/dev/raw-intake/omi",
36
+ "alias": "jomi",
37
+ "description": "OMI wearable transcripts",
38
+ "type": "brain"
39
+ },
40
+ {
41
+ "key": "clients",
42
+ "path": "~/dev/clients",
43
+ "alias": "jclients",
44
+ "description": "Client work root",
45
+ "type": "client"
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "video-projects-root": "~/dev/video-projects",
3
+ "ecamm-recording-folder": "~/ecamm",
4
+ "download-folder": "~/Downloads",
5
+ "download-image-folder": "~/Downloads/images",
6
+ "aliases-output-path": "~/.config/appydave/aliases.sh",
7
+ "brains-root-path": "~/dev/brains",
8
+ "omi-directory-path": "~/dev/raw-intake/omi"
9
+ }
@@ -8,39 +8,22 @@
8
8
  # min_results: Minimum results to be considered a "good" match (default: 1)
9
9
  # max_results: Maximum results to be considered a "good" match (default: 15)
10
10
  #
11
- # The OMI skill can extend this file by appending new entries under queries:.
11
+ # This is the bundled default it ships with the gem and is bootstrapped to
12
+ # ~/.config/appydave/random-queries.yml on first use.
13
+ #
14
+ # All queries here use generic flags (--active, --category, --routing) that
15
+ # work regardless of what brain names or folder structure a user has.
16
+ #
17
+ # To add personal queries (brain names, custom paths), edit your own copy at
18
+ # ~/.config/appydave/random-queries.yml after it has been bootstrapped.
12
19
 
13
20
  queries:
14
- # --- Brain queries ---
15
- - label: "What do I know about paperclip?"
16
- command: "query_brain --find paperclip"
17
- min_results: 1
18
- max_results: 20
19
-
20
- - label: "What do I know about OMI?"
21
- command: "query_brain --find omi"
22
- min_results: 1
23
- max_results: 20
24
-
25
- - label: "What do I know about BMAD method?"
26
- command: "query_brain --find bmad"
27
- min_results: 1
28
- max_results: 20
29
-
30
- - label: "What do I know about agentic engineering?"
31
- command: "query_brain --find agentic-engineering"
32
- min_results: 1
33
- max_results: 30
21
+ # --- Brain queries (generic — works for any user with a configured brains-root-path) ---
34
22
 
35
- - label: "What are my active high-priority brains?"
23
+ - label: "What are my most active areas of knowledge?"
36
24
  command: "query_brain --active"
37
- min_results: 5
38
- max_results: 50
39
-
40
- - label: "What do I know about Claude / Anthropic?"
41
- command: "query_brain --find anthropic"
42
25
  min_results: 1
43
- max_results: 20
26
+ max_results: 50
44
27
 
45
28
  - label: "Browse my agent systems knowledge"
46
29
  command: "query_brain --category agent-systems"
@@ -52,17 +35,18 @@ queries:
52
35
  min_results: 1
53
36
  max_results: 30
54
37
 
55
- - label: "What do I know about context engineering?"
56
- command: "query_brain --find context-engineering"
38
+ - label: "Browse my tools and utilities knowledge"
39
+ command: "query_brain --category tools"
57
40
  min_results: 1
58
- max_results: 20
41
+ max_results: 30
59
42
 
60
- - label: "What do I know about FliVideo?"
61
- command: "query_brain --find flivideo"
43
+ - label: "Browse my workflows knowledge"
44
+ command: "query_brain --category workflows"
62
45
  min_results: 1
63
- max_results: 20
46
+ max_results: 30
47
+
48
+ # --- OMI queries (generic — works for any user with a configured omi-directory-path) ---
64
49
 
65
- # --- OMI queries ---
66
50
  - label: "Recent things I learned (TIL)"
67
51
  command: "query_omi --routing til --limit 5"
68
52
  min_results: 1
@@ -83,16 +67,6 @@ queries:
83
67
  min_results: 1
84
68
  max_results: 10
85
69
 
86
- - label: "Recent OMI conversations about paperclip"
87
- command: "query_omi --brain paperclip --limit 3"
88
- min_results: 1
89
- max_results: 3
90
-
91
- - label: "Recent OMI conversations about BMAD"
92
- command: "query_omi --brain bmad --limit 3"
93
- min_results: 1
94
- max_results: 3
95
-
96
70
  - label: "What was I planning recently?"
97
71
  command: "query_omi --activity planning --days 14 --limit 5"
98
72
  min_results: 1
@@ -102,3 +76,8 @@ queries:
102
76
  command: "query_omi --activity learning --days 14 --limit 5"
103
77
  min_results: 1
104
78
  max_results: 5
79
+
80
+ - label: "Recent meeting notes"
81
+ command: "query_omi --activity meeting --days 30 --limit 5"
82
+ min_results: 1
83
+ max_results: 5
@@ -0,0 +1,24 @@
1
+ {
2
+ "generated": "2026-04-05",
3
+ "generator": "system-context",
4
+ "project": "appydave-tools",
5
+ "pattern": "ruby-gem",
6
+ "globs": {
7
+ "docs": ["docs/**/*.md"],
8
+ "config": ["config/**/*.json"],
9
+ "lib": ["lib/**/*.rb"],
10
+ "bin": ["bin/*"],
11
+ "tests": ["spec/**/*_spec.rb"],
12
+ "planning": ["docs/planning/**/*.md"],
13
+ "context": ["CLAUDE.md", "CONTEXT.md"]
14
+ },
15
+ "aliases": {
16
+ "source": ["lib", "bin"],
17
+ "specs": ["tests"]
18
+ },
19
+ "composites": {
20
+ "understand": ["context", "docs", "config"],
21
+ "codebase": ["lib", "bin"],
22
+ "full": ["*"]
23
+ }
24
+ }
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Multi-User Support — AppyDave Tools
3
+ status: planning
4
+ created: 2026-04-05
5
+ context: Lars onboarding — first external user of appydave-tools
6
+ ---
7
+
8
+ # Multi-User Support
9
+
10
+ ## Current State
11
+
12
+ AppyDave Tools was built for a single user on David's M4 creator machine. It is not intentionally single-user — the architecture is already mostly correct — but it has never been tested with a second person's folder structure.
13
+
14
+ **What works for multi-user today:**
15
+ - Config is stored in `~/.config/appydave/` — per-user, not shared, no collision
16
+ - `gem install appydave-tools` gives Lars a clean install with no locations
17
+ - All tools read their paths from `~/.config/appydave/locations.json` at runtime
18
+
19
+ **What doesn't work yet:**
20
+ - Lars starts with an empty `locations.json` — no seed, no onboarding flow
21
+ - Lars's dev folder structure is unknown (capturing via `ls ~/dev/` in next relay session)
22
+ - David's `locations.json` has 100 entries, all pointing to `/Users/davidcruwys/` — not portable
23
+ - Brain query, OMI query, and LLM context tools likely assume specific location keys exist (e.g., `brain`, `omi`) — if Lars's keys are different or missing, these will fail silently or error
24
+
25
+ ---
26
+
27
+ ## Tools Lars Needs
28
+
29
+ ### 1. Jump (immediate value)
30
+
31
+ The `jump` command generates shell aliases for folder navigation. Lars currently has only `jb` (jump to brain) — hardcoded, not managed by this tool.
32
+
33
+ **What Lars gets after setup:**
34
+ - Any folder registered in `locations.json` becomes a `j<alias>` shell alias
35
+ - Running `jump generate` writes a `.aliases` file; sourcing it activates them
36
+ - He can register his `~/dev/clients/`, relay folder, growth-intelligence repo, etc.
37
+
38
+ **Blocker:** He needs entries in `locations.json` before any aliases are generated.
39
+
40
+ ### 2. Brain Query
41
+
42
+ Queries Lars's second brain folder structure. Likely reads from a location keyed `brain` in `locations.json`.
43
+
44
+ **Risk:** Key name may be hardcoded. Need to verify the tool reads `brain` key or is configurable.
45
+
46
+ ### 3. OMI Query
47
+
48
+ Queries saved OMI transcripts. Likely reads from a location keyed `omi` or a path in `settings.json`.
49
+
50
+ **Risk:** Lars's OMI intake is at `~/dev/raw-intake/omi/` — this needs to be registered in his config.
51
+
52
+ ### 4. LLM Context Builder
53
+
54
+ Builds context bundles for pasting into LLM sessions. Probably reads from multiple registered locations.
55
+
56
+ **Risk:** May depend on several location keys existing. Needs testing with minimal config.
57
+
58
+ ---
59
+
60
+ ## Installation Plan for Lars
61
+
62
+ ```bash
63
+ gem install appydave-tools
64
+ ```
65
+
66
+ Then verify:
67
+
68
+ ```bash
69
+ appydave --version
70
+ appydave jump report
71
+ ```
72
+
73
+ `jump report` with an empty `locations.json` should return zero locations without error — if it crashes, that's the first bug to fix.
74
+
75
+ ### After Install — Bootstrap Lars's Locations
76
+
77
+ Lars needs a minimal seed `locations.json` tailored to his machine. Suggested starting set once we know his `~/dev/` structure:
78
+
79
+ | Key | Path (approximate) | Purpose |
80
+ |-----|--------------------|---------|
81
+ | `dev` | `~/dev` | Root dev folder |
82
+ | `brain` | `~/dev/brains/` | Second brain |
83
+ | `omi` | `~/dev/raw-intake/omi/` | OMI transcripts |
84
+ | `clients` | `~/dev/clients/` | Client work |
85
+ | `growth` | `~/dev/clients/lars-projects/growth-intelligence/` | Growth Intelligence repo |
86
+ | `relay` | `~/Dropbox/relay/people/david-lars/` | Relay folder |
87
+
88
+ Lars adds these via `appydave jump add` or by editing `~/.config/appydave/locations.json` directly.
89
+
90
+ ---
91
+
92
+ ## Known Gaps to Resolve
93
+
94
+ 1. **Empty-config behaviour** — run all four tools with a blank `locations.json` and confirm they fail gracefully, not with a Ruby stack trace
95
+ 2. **Location key conventions** — are keys like `brain` and `omi` hardcoded in brain-query and omi-query, or configurable? Document the expected keys.
96
+ 3. **Aliases output path** — `aliases-output-path` in `settings.json` tells jump where to write the `.aliases` file. Lars needs this set before `jump generate` works. Default: `~/.config/appydave/aliases.sh` (check current default).
97
+ 4. **Shell sourcing** — after `jump generate`, Lars needs `source ~/.config/appydave/aliases.sh` (or equivalent) in his `.zshrc`. This needs to be part of the setup guide.
98
+ 5. **Ruby version** — gemspec requires `>= 2.7`. Lars's Ruby version is unknown — check during session.
99
+
100
+ ---
101
+
102
+ ## What This Is Not
103
+
104
+ This is not a multi-tenant SaaS problem. Each user has their own machine, their own `~/.config/appydave/`, and their own gem install. There is no shared state. The "multi-user support" work is really:
105
+
106
+ - Making sure the tools don't assume David's paths
107
+ - Providing a repeatable onboarding flow for a new machine
108
+ - Writing a short setup guide Lars can follow independently next time