| 753 | } |
| 754 | |
| 755 | func parseShellRC(path, modelOverride string) (ResolvedEndpoint, bool, error) { |
| 756 | data, err := os.ReadFile(path) |
| 757 | if err != nil { |
| 758 | return ResolvedEndpoint{}, false, nil |
| 759 | } |
| 760 | |
| 761 | var baseURL, token, model string |
| 762 | for _, line := range strings.Split(string(data), "\n") { |
| 763 | line = strings.TrimSpace(line) |
| 764 | matches := exportRe.FindStringSubmatch(line) |
| 765 | if matches == nil { |
| 766 | continue |
| 767 | } |
| 768 | key := matches[1] |
| 769 | value := matches[2] |
| 770 | if value == "" { |
| 771 | value = matches[3] |
| 772 | } |
| 773 | if value == "" { |
| 774 | value = matches[4] |
| 775 | } |
| 776 | value = strings.TrimSpace(value) |
| 777 | |
| 778 | switch key { |
| 779 | case "ANTHROPIC_BASE_URL": |
| 780 | baseURL = value |
| 781 | case "ANTHROPIC_AUTH_TOKEN": |
| 782 | token = value |
| 783 | case "ANTHROPIC_MODEL": |
| 784 | model = value |
| 785 | } |
| 786 | } |
| 787 | if modelOverride != "" { |
| 788 | model = modelOverride |
| 789 | } |
| 790 | |
| 791 | if baseURL == "" || token == "" || model == "" { |
| 792 | return ResolvedEndpoint{}, false, nil |
| 793 | } |
| 794 | |
| 795 | url := ensureMessagesSuffix(baseURL) |
| 796 | |
| 797 | // Claude Code shell rc tokens are OAuth/Bearer-style credentials. |
| 798 | return ResolvedEndpoint{URL: url, Token: token, Model: model, Protocol: ProtocolAnthropic, AuthHeader: "authorization", Source: "Shell rc file"}, true, nil |
| 799 | } |
| 800 | |
| 801 | func defaultAuthHeader(protocol string) string { |
| 802 | // auth_header is Anthropic-only; OpenAI-compatible clients keep API key auth. |