Tags Filtering Feature Spec
Overview
Add a tags column to the companies schema to enable filtering companies by
descriptive keywords. Tags are admin-defined, shared across companies, and used
to narrow the scan scope.
Column Schema
- Column name:
tags
- Position: last column in
companies.csv
- Format: comma-separated lowercase string, no spaces after commas
- Example:
python,ai,startup / fintech,s&p500,enterprise
- Empty value: valid — means no tags assigned to that company
Filtering Rules
- Tags filter is configured in
config.json under key "tags" as a list of strings
- Example:
"tags": ["ai", "startup"]
- If
"tags" is absent or empty list → no filtering, scan all companies (current behavior preserved)
- Tag matching is OR logic — company is included if it has any of the configured tags
- Tag filter is applied on top of the existing
no_click=TRUE filter
- Tag matching is case-insensitive at the application level (values stored lowercase)
Config
{
"tags": ["ai", "startup"]
}
- Default value in
CONFIG_DEFAULTS: "tags": []
- Tags are not configurable via CLI flags —
config.json only
Files Affected
| File |
Change |
data/companies.csv |
Add tags column |
tests/test_data/companies.csv |
Add tags column with example values |
config.py |
Add "tags": [] to CONFIG_DEFAULTS |
config.json |
Add "tags": [] entry |
csv_io.py |
load_companies() accepts tags filter and applies it |
main.py |
Pass config["tags"] to load_companies() |
integrations/scheduler.py |
Pass config["tags"] to load_companies() |
tests/test_load_companies.py |
Add tag filtering test cases |
CLAUDE.md |
Document tags column and filtering behavior |
README.md |
Document tags column, config key, and filtering behavior |
Future Considerations
- Postgres migration:
tags column maps to TEXT[] or a junction table
- Central vs user companies DB:
tags column is identical in both
- User-suggested tags: predefined by admin for now; user suggestions planned
Claude Code task
CC Task: Add Tags Filtering Feature
Context
Adding a tags column to the companies schema and optional tag-based filtering
to load_companies(). No changes to scanner logic.
Steps
1. config.py
Add "tags": [] to CONFIG_DEFAULTS.
2. config.json
Add "tags": [] entry.
3. csv_io.py — load_companies()
- Add optional
tags: list[str] parameter (default [])
- After existing
no_click=TRUE filter, apply tags filter:
- If
tags is empty → no filtering (include all)
- If
tags is non-empty → include company only if its tags column value
shares at least one tag with the filter list (OR logic)
- Normalize both sides to lowercase before comparing
- Handle empty/missing
tags column value gracefully (exclude company if
tags filter is active and company has no tags)
- Read
tags field from CSV row and include it in the returned company dict
4. main.py
Pass tags=config.get("tags", []) to load_companies().
5. integrations/scheduler.py
Pass tags=config.get("tags", []) to load_companies().
6. tests/test_data/companies.csv
Add tags column. Assign example tags to several rows:
- a few companies with
ai
- a few with
startup
- a few with
fintech or s&p500
- a few with multiple tags
- a few with empty tags
7. tests/test_load_companies.py
Add test cases:
test_tags_column_present_in_returned_dict — tags key exists in every dict
test_tags_filter_or_logic — company with any matching tag is included
test_tags_filter_excludes_non_matching — company with no matching tag excluded
test_tags_filter_empty_config_includes_all — empty tags list = no filtering
test_tags_filter_company_with_no_tags_excluded — company with empty tags column is excluded when filter is active
8. CLAUDE.md
Under companies.csv requirements section add:
tags column format and filtering behavior
9. README.md
- Add
tags to the companies CSV column table
- Document
tags config key in the Configuration section
Tags Filtering Feature Spec
Overview
Add a
tagscolumn to the companies schema to enable filtering companies bydescriptive keywords. Tags are admin-defined, shared across companies, and used
to narrow the scan scope.
Column Schema
tagscompanies.csvpython,ai,startup/fintech,s&p500,enterpriseFiltering Rules
config.jsonunder key"tags"as a list of strings"tags": ["ai", "startup"]"tags"is absent or empty list → no filtering, scan all companies (current behavior preserved)no_click=TRUEfilterConfig
{ "tags": ["ai", "startup"] }CONFIG_DEFAULTS:"tags": []config.jsononlyFiles Affected
data/companies.csvtagscolumntests/test_data/companies.csvtagscolumn with example valuesconfig.py"tags": []toCONFIG_DEFAULTSconfig.json"tags": []entrycsv_io.pyload_companies()acceptstagsfilter and applies itmain.pyconfig["tags"]toload_companies()integrations/scheduler.pyconfig["tags"]toload_companies()tests/test_load_companies.pyCLAUDE.mdREADME.mdFuture Considerations
tagscolumn maps toTEXT[]or a junction tabletagscolumn is identical in bothClaude Code task
CC Task: Add Tags Filtering Feature
Context
Adding a
tagscolumn to the companies schema and optional tag-based filteringto
load_companies(). No changes to scanner logic.Steps
1.
config.pyAdd
"tags": []toCONFIG_DEFAULTS.2.
config.jsonAdd
"tags": []entry.3.
csv_io.py—load_companies()tags: list[str]parameter (default[])no_click=TRUEfilter, apply tags filter:tagsis empty → no filtering (include all)tagsis non-empty → include company only if itstagscolumn valueshares at least one tag with the filter list (OR logic)
tagscolumn value gracefully (exclude company iftags filter is active and company has no tags)
tagsfield from CSV row and include it in the returned company dict4.
main.pyPass
tags=config.get("tags", [])toload_companies().5.
integrations/scheduler.pyPass
tags=config.get("tags", [])toload_companies().6.
tests/test_data/companies.csvAdd
tagscolumn. Assign example tags to several rows:aistartupfintechors&p5007.
tests/test_load_companies.pyAdd test cases:
test_tags_column_present_in_returned_dict—tagskey exists in every dicttest_tags_filter_or_logic— company with any matching tag is includedtest_tags_filter_excludes_non_matching— company with no matching tag excludedtest_tags_filter_empty_config_includes_all— empty tags list = no filteringtest_tags_filter_company_with_no_tags_excluded— company with empty tags column is excluded when filter is active8.
CLAUDE.mdUnder
companies.csv requirementssection add:tagscolumn format and filtering behavior9.
README.mdtagsto the companies CSV column tabletagsconfig key in the Configuration section